Como pode um arquivo .bat ser ‘convertido’ para .exe sem ferramentas de terceiros?

Existem muitas razões para querer ‘converter’ um .bat para .exe – para ocultar / ofuscar a implementação, senhas, caminho para resources, para criar um serviço a partir de um arquivo em lote … e principalmente para tornar seu trabalho mais complexo e importante do que realmente é.

Há também muitas razões para não querer usar ferramentas de terceiros.

E se você quiser ‘converter’ um arquivo em lote para .exe sem software externo? (A conversão está entre aspas porque eu não acho que haja realmente uma maneira de compilar um arquivo em lote para executável. Existem muitas técnicas e bugs abusivos usados ​​extensivamente e todas as ferramentas que eu conheço criam um arquivo temporário .bat e chame-o )

Uma abordagem muito óbvia é usar o IEXPRESS – a antiga ferramenta interna que cria pacotes de extração automática e é capaz de executar comandos pós-extração. Então aqui está o arquivo sed.exe / sed / directive do iEXPRESS que cria um .exe autoextraível com o pacote .bat. Ele aceita dois argumentos – o arquivo .bat que você deseja converter e o executável de destino:

  ;@echo off ; rem https://github.com/npocmaka/batch.scripts/edit/master/hybrids/iexpress/bat2exeIEXP.bat ;if "%~2" equ "" ( ; echo usage: %~nx0 batFile.bat target.Exe ;) ;set "target.exe=%__cd__%%~2" ;set "batch_file=%~f1" ;set "bat_name=%~nx1" ;set "bat_dir=%~dp1" ;copy /y "%~f0" "%temp%\2exe.sed" >nul ;(echo()>>"%temp%\2exe.sed" ;(echo(AppLaunched=cmd.exe /c "%bat_name%")>>"%temp%\2exe.sed" ;(echo(TargetName=%target.exe%)>>"%temp%\2exe.sed" ;(echo(FILE0="%bat_name%")>>"%temp%\2exe.sed" ;(echo([SourceFiles])>>"%temp%\2exe.sed" ;(echo(SourceFiles0=%bat_dir%)>>"%temp%\2exe.sed" ;(echo([SourceFiles0])>>"%temp%\2exe.sed" ;(echo(%%FILE0%%=)>>"%temp%\2exe.sed" ;iexpress /n /q /m %temp%\2exe.sed ;del /q /f "%temp%\2exe.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= AdminQuietInstCmd= UserQuietInstCmd= 

exemplo:

 bat2exeIEXP.bat myBatFile.bat MyExecutable.exe 

Isso deve funcionar praticamente em todas as máquinas Windows existentes, mas tem uma limitação importante – você não pode passar argumentos para o arquivo .exe criado

Então, uma outra abordagem possível é olhar para os compiladores .NET (novamente deve estar disponível em quase todas as máquinas vencedoras). Eu escolhi o Jscript.net . Este é um script híbrido jscript.net / .bat que lerá o conteúdo do arquivo .batch. Ele criará outro jscript.net com o conteúdo do arquivo .bat e, após a compilation, criará um novo arquivo bat na pasta temp e o chamará. E vai aceitar argumentos de linha de comando (explicado pode parecer complexo, mas na verdade é simples):

 @if (@X)==(@Y) @end /* JScript comment @echo off setlocal del %~n0.exe /q /s >nul 2>nul for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d /o:-n "%SystemRoot%\Microsoft.NET\Framework\*jsc.exe"') do ( set "jsc=%%v" ) if not exist "%~n0.exe" ( "%jsc%" /nologo /out:"%~n0.exe" "%~dpsfnx0" ) %~n0.exe "%jsc%" %* del /q /f %~n0.exe 1>nul 2>nul endlocal & exit /b %errorlevel% */ //https://github.com/npocmaka/batch.scripts/blob/master/hybrids/.net/bat2exe.bat import System; import System; import System.IO; import System.Diagnostics; var arguments:String[] = Environment.GetCommandLineArgs(); if (arguments.length<3){ Console.WriteLine("Path to cmd\bat file not given"); Environment.Exit(1); } var binName=Path.GetFileName(arguments[2])+".exe"; if(arguments.length>3){ binName=Path.GetFileName(arguments[3]); } var batchContent:byte[]= File.ReadAllBytes(arguments[2]); var compilerLoc=arguments[1]; var content="[" for (var i=0;i 

É um pouco um POC, mas as bibliotecas System.Diagnostics e System.IO do .NET são poderosas o suficiente para adicionar resources como início oculto, codificação e etc. Você também pode verificar as opções de compilation do jsc.exe para ver o que mais é capaz (como adicionar resources ).

Eu prometo um upvote para cada melhoria sobre o método .net 🙂

ATUALIZAÇÃO: o segundo script foi alterado e agora o exe do arquivo bat convertido pode ser iniciado com duplo clique. Ele usa a mesma interface do script anterior:

 bat2exejs.bat example.bat example.exe