Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
ms_windows_ms_sql:bat_and_powershell_to_exe [2019/10/31 12:39] – [Скрываем окно любого процесса средствами Powershell] adminms_windows_ms_sql:bat_and_powershell_to_exe [2019/11/06 14:04] (current) admin
Line 1: Line 1:
 +====== Задача ======
 +У меня есть скрипт на **Powershell**. Мне нужно сделать из него исполняемый файл. Желательно - встроенными средствами **Windows** (10/2016). \\
 +\\
 +Так как я давно знаю о существовании **bat2exe**, то задача разбивается на две подзадачи. \\
 +  * встроить многострочный скрипт **Powershell** в bat-скрипт
 +  * конвертировать полученный **bat**-скрипт в исполняемый **exe**-файл
 +===== Встроить PowerShell-скрипт в bat-скрипт =====
 +https://stackoverflow.com/questions/9366080/batch-launching-powershell-with-a-multiline-command-parameter \\
 +Оказалось все несложно при соблюдении некоторых условностей. \\
 +Для исполнения многострочной команды **powershell** внутри **bat**-скрипта нужно делать так:
 +<code>powershell -command ^
  
 +for ($i=1; $i -lt 10; $i++){^
 +
 +   Write-Host $(\"Iteration - $i\") }^
 +
 +Write-Host
 +</code>
 +Это **bat**-скрипт, исполняющий блок кода **Powershell**. \\
 +На что обратить внимание:
 +  - Строки, после которых будет продолжение - оканчиваются символом **^**. Последняя строка блока **powershell** - без этого символа!
 +  - Между строками - пустые строки. Без них команды **powershell** склеются в одну длинную строку, что допустимо не всегда.
 +  - Экранирование символов. В данном случае экранированы двойные кавычки **"**. Это нужно не всегда, но об этом нужно помнить, если что-то работает не так как нужно.
 +  - Не стоит оставлять фигурные скобки в одиночестве на строке.
 +
 +Вот однострочник **bash**, который берет заданный Powershell-скрипт и выводит соответствующий ему bat-скрипт:
 +  echo -e "powershell -command ^\n\n`sed 's/"/\\\\"/g' ./Script.ps1 | sed '/^#.*$/d' | sed '/^[[:space:]]*$/d' | sed 's/$/\^\r\n/g'`\n\n#"
 +Вот более сложный скрипт, который запускает **IDE Eclipse**, установленную в **WSL** (**Windows Subsystem For Linux**):
 +<code>powershell -command ^
 +
 +$UbuntuAppxPackagename='CanonicalGroupLimited.Ubuntu18.04onWindows'^
 +
 +$ubuntu_exe='ubuntu1804.exe'^
 +
 +$ubuntu_exe=\"$($(Get-AppxPackage | Where {$_.Name -eq $UbuntuAppxPackagename }).InstallLocation)\$ubuntu_exe\"^
 +
 +$username=$(whoami /upn).Split('@')[0]^
 +
 +$XServerProcessName='vcxsrv'^
 +
 +$XServerExePath='C:\Program Files\VcXsrv\vcxsrv.exe'^
 +
 +$XServerArguments=':0 -multiwindow -clipboard -wgl'^
 +
 +$cmd = '\"' + $ubuntu_exe + '\" ' + \"run useradd -m -s /bin/bash $username\"^
 +
 +cmd /c $cmd^
 +
 +if ($(Get-Process -Name $XServerProcessName) -eq $null) { Start-Process -NoNewWindow -FilePath $XServerExePath -ArgumentList $XServerArguments }^
 +
 +$cmd = '\"' + $ubuntu_exe + '\" ' + \"run sudo -u $username DISPLAY=:0.0 /opt/eclipse/eclipse\"^
 +
 +cmd /c $cmd</code>
 +
 +===== Конвертирование bat в exe с помощью встронных средств Windows =====
 +https://stackoverflow.com/questions/51098378/converting-bat-to-exe-with-no-additional-external-software-create-sfx/51104332 \\
 +https://github.com/npocmaka/batch.scripts/edit/master/hybrids/iexpress/bat2exeIEXP.bat \\
 +\\
 +Это вообще похоже на магию. \\
 +Есть такая утилита **IEXPRESS**. Она есть во всех версиях Windows, начиная с Windows 2000 и предназначена для создания самораспаковывающихся архивов из набора файлов. \\
 +Вот **bat**-файл, который делает то что нужно. \\
 +Пользоваться им очень просто - создаем файл с этим скриптом и перетаскиваем на его иконку **bat**-скрипт, который нужно сконвертировать в **exe**. Всё. Рядом с исходным скриптом появится **exe**-файл.
 +<code>;@echo off
 +;Title Converting batch scripts to file.exe with iexpress
 +;Mode 75,3 & color 0A
 +;Rem Original Script https://github.com/npocmaka/batch.scripts/edit/master/hybrids/iexpress/bat2exeIEXP.bat
 +;echo(
 +;if "%~1" equ "" (
 +    ;echo  Usage : Drag and Drop your batch file over this script:"%~nx0"  
 +    ;Timeout /T 5 /nobreak>nul & Exit
 +;)
 +;set "target.exe=%__cd__%%~n1.exe"
 +;set "batch_file=%~f1"
 +;set "bat_name=%~nx1"
 +;set "bat_dir=%~dp1"
 +;Set "sed=%temp%\2exe.sed"
 +;echo              Please  wait a while ...  Creating "%~n1.exe" ...
 +;copy /y "%~f0" "%sed%" >nul
 +;(
 +    ;(echo()
 +    ;(echo(AppLaunched=cmd /c "%bat_name%")
 +    ;(echo(TargetName=%target.exe%)
 +    ;(echo(FILE0="%bat_name%")
 +    ;(echo([SourceFiles])
 +    ;(echo(SourceFiles0=%bat_dir%)
 +    ;(echo([SourceFiles0])
 +    ;(echo(%%FILE0%%=)
 +;)>>"%sed%"
 +
 +;iexpress /n /q /m %sed%
 +;del /q /f "%sed%"
 +;exit /b 0
 +
 +[Version]
 +Class=IEXPRESS
 +SEDVersion=3
 +[Options]
 +PackagePurpose=InstallApp
 +ShowInstallProgramWindow=0
 +HideExtractAnimation=1
 +UseLongFileName=1
 +InsideCompressed=0
 +CAB_FixedSize=0
 +CAB_ResvCodeSigning=0
 +RebootMode=N
 +InstallPrompt=%InstallPrompt%
 +DisplayLicense=%DisplayLicense%
 +FinishMessage=%FinishMessage%
 +TargetName=%TargetName%
 +FriendlyName=%FriendlyName%
 +AppLaunched=%AppLaunched%
 +PostInstallCmd=%PostInstallCmd%
 +AdminQuietInstCmd=%AdminQuietInstCmd%
 +UserQuietInstCmd=%UserQuietInstCmd%
 +SourceFiles=SourceFiles
 +
 +[Strings]
 +InstallPrompt=
 +DisplayLicense=
 +FinishMessage=
 +FriendlyName=-
 +PostInstallCmd=<None>
 +AdminQuietInstCmd=</code>
 +
 +Единственным недостатком этого метода можно считать открытое окно консоли на фоне.
 +
 +====== Скрываем окно любого процесса средствами Powershell ======
 +https://community.idera.com/database-tools/powershell/powertips/b/tips/posts/show-or-hide-windows \\
 +Нижеприведенный powershell-код позволяет скрыть окно любого процесса:
 +<code>Enum ShowStates
 +{
 +  Hide = 0
 +  Normal = 1
 +  Minimized = 2
 +  Maximized = 3
 +  ShowNoActivateRecentPosition = 4
 +  Show = 5
 +  MinimizeActivateNext = 6
 +  MinimizeNoActivate = 7
 +  ShowNoActivate = 8
 +  Restore = 9
 +  ShowDefault = 10
 +  ForceMinimize = 11
 +}
 +
 +
 +# the C#-style signature of an API function (see also www.pinvoke.net)
 +$code = '[DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);'
 +
 +# add signature as new type to PowerShell (for this session)
 +$type = Add-Type -MemberDefinition $code -Name myAPI -PassThru
 +
 +# access a process
 +# (in this example, we are accessing the current PowerShell host
 +#  with its process ID being present in $pid, but you can use
 +#  any process ID instead)
 +$process = Get-Process -Id $PID
 +
 +# get the process window handle
 +$hwnd = $process.MainWindowHandle
 +
 +# apply a new window size to the handle, i.e. hide the window completely
 +$type::ShowWindowAsync($hwnd, [ShowStates]::Hide)
 +
 +Start-Sleep -Seconds 2
 +# restore the window handle again
 +$type::ShowWindowAsync($hwnd, [ShowStates]::Show)</code>
 +
 +Чтобы работало в старых версиях **Powershell** (2-4) определение типов видимости нужно делать так:
 +<code>Add-Type -TypeDefinition '
 +public enum ShowStates
 +{
 +    Hide = 0,
 +    Normal = 1,
 +    Minimized = 2,
 +    Maximized = 3,
 +    ShowNoActivateRecentPosition = 4,
 +    Show = 5,
 +    MinimizeActivateNext = 6,
 +    MinimizeNoActivate = 7,
 +    ShowNoActivate = 8,
 +    Restore = 9,
 +    ShowDefault = 10,
 +    ForceMinimize = 11,
 +}
 +'</code>
 +
 +Вот bat-скрипт, который скрывает окно консоли и делает нужную работу (открывает процесс средствами powershell):
 +<code>powershell -command ^
 +
 +Enum ShowStates {^
 +
 +  Hide = 0^
 +
 +  Normal = 1^
 +
 +  Minimized = 2^
 +
 +  Maximized = 3^
 +
 +  ShowNoActivateRecentPosition = 4^
 +
 +  Show = 5^
 +
 +  MinimizeActivateNext = 6^
 +
 +  MinimizeNoActivate = 7^
 +
 +  ShowNoActivate = 8^
 +
 +  Restore = 9^
 +
 +  ShowDefault = 10^
 +
 +  ForceMinimize = 11 } ^
 +
 +$code = '[DllImport(\"user32.dll\")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);'^
 +
 +$type = Add-Type -MemberDefinition $code -Name myAPI -PassThru ^
 +
 +$ParentProcessId = $(Get-CimInstance Win32_Process -Filter \"ProcessId = $PID\").ParentProcessId^
 +
 +$process = Get-Process -Id $ParentProcessId^
 +
 +$hwnd = $process.MainWindowHandle^
 +
 +$type::ShowWindowAsync($hwnd, [ShowStates]::Hide)^
 +
 +#############################################################^
 +
 +$UbuntuAppxPackagename=\"CanonicalGroupLimited.Ubuntu18.04onWindows\"^
 +
 +$ubuntu_exe=\"$($(Get-AppxPackage | Where {$_.Name -eq $UbuntuAppxPackagename }).InstallLocation)\ubuntu1804.exe\"^
 +
 +$username=$(whoami /upn).Split('@')[0]^
 +
 +$XServerProcessName='vcxsrv'^
 +
 +$XServerExePath='C:\Program Files\VcXsrv\vcxsrv.exe'^
 +
 +$XServerArguments=':0 -multiwindow -clipboard -wgl'^
 +
 +$cmd = '\"' + $ubuntu_exe + '\" ' + \"run useradd -m -s /bin/bash $username\"^
 +
 +cmd /c $cmd^
 +
 +if ($(Get-Process -Name $XServerProcessName) -eq $null) { Start-Process -NoNewWindow -FilePath $XServerExePath -ArgumentList $XServerArguments }^
 +
 +$cmd = '\"' + $ubuntu_exe + '\" ' + \"run sudo -u $username DISPLAY=:0.0 /opt/eclipse/eclipse\"^
 +
 +cmd /c $cmd
 +
 +</code>
  • ms_windows_ms_sql/bat_and_powershell_to_exe.txt
  • Last modified: 2019/11/06 14:04
  • by admin