Как файл.bat "конвертировать" в.exe без сторонних инструментов?
Есть много причин, чтобы хотеть "преобразовать" .bat
в .exe
- скрыть / запутать реализацию, пароли, путь к ресурсам, создать сервис из командного файла... и, главным образом, сделать вашу работу более сложной и важной, чем она есть на самом деле.
Есть также много причин, чтобы не использовать сторонние инструменты.
Так что, если вы хотите "преобразовать" командный файл в .exe
без внешнего софта?
(convert находится в кавычках, потому что я не думаю, что на самом деле есть способ скомпилировать командный файл в исполняемый файл. Существует слишком много ошибочных извилистых методов и ошибок, которые широко используются, и все инструменты, которые я знаю, фактически создают временные .bat
файл, а затем назвать его)
7 ответов
Один очень очевидный подход заключается в использовании IEXPRESS - древнего встроенного инструмента, который создает самораспаковывающиеся пакеты и способен выполнять команды после извлечения. Итак, вот файл IEXPRESS sed-directive /.bat, который создает самораспаковывающийся.exe с упакованным.bat. Он принимает два аргумента - файл.bat, который вы хотите преобразовать, и целевой исполняемый файл:
;@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=<None>
AdminQuietInstCmd=
UserQuietInstCmd=
пример:
bat2exeIEXP.bat myBatFile.bat MyExecutable.exe
Это должно работать практически на каждой машине с Windows, но имеет одно важное ограничение - вы не можете передавать аргументы в созданный файл.exe
Так что еще один возможный подход - посмотреть на.NET-компиляторы (опять же, они должны быть доступны почти на каждой выигрышной машине). Я выбрал Jscript.net. Это гибрид jscript.net
/.bat
скрипт, который будет читать содержимое файла.batch. Создаст еще один jscript.net с содержимым файла.bat, а после компиляции создаст новый файл bat в папке temp и вызовет его. И примет аргументы командной строки. может показаться сложным, но на самом деле все просто):
@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<batchContent.length-1;i++){
content=content+batchContent[i]+","
}
content=content+batchContent[batchContent.length-1]+"]";
var temp=Path.GetTempPath();
var dt=(new Date()).getTime();
var tempJS=temp+"\\2exe"+dt+".js";
var toCompile="\r\n\
import System;\r\n\
import System.IO;\r\n\
import System.Diagnostics;\r\n\
var batCommandLine:String='';\r\n\
//Remove the executable name from the command line\r\n\
try{\r\n\
var arguments:String[] = Environment.GetCommandLineArgs();\r\n\
batCommandLine=Environment.CommandLine.substring(arguments[0].length,Environment.CommandLine.length);\r\n\
}catch(e){}\r\n\
var content2:byte[]="+content+";\r\n\
var dt=(new Date()).getTime();\r\n\
var temp=Path.GetTempPath();\r\n\
var nm=Process.GetCurrentProcess().ProcessName.substring(0,Process.GetCurrentProcess().ProcessName.length-3);\r\n\
var tempBatPath=Path.Combine(temp,nm+dt+'.bat');\r\n\
File.WriteAllBytes(tempBatPath,content2);\r\n\
var pr=System.Diagnostics.Process.Start('cmd.exe','/c '+' '+tempBatPath+' '+batCommandLine);\r\n\
pr.WaitForExit();\r\n\
File.Delete(tempBatPath);\r\n\
";
File.WriteAllText(tempJS,toCompile);
var pr=System.Diagnostics.Process.Start(compilerLoc,'/nologo /out:"'+binName+'" "'+tempJS+'"');
pr.WaitForExit();
File.Delete(tempJS);
Это скорее POC, но библиотеки.NET System.Diagnostics и System.IO достаточно мощные, чтобы добавлять такие функции, как скрытый запуск, шифрование и т. Д. Вы также можете проверить параметры компиляции jsc.exe, чтобы увидеть, на что еще способен (например, добавить ресурсы).).
Я обещаю приветствовать каждое улучшение по сравнению с методом.NET:-)
ОБНОВЛЕНИЕ: второй скрипт был изменен, и теперь исполняемый файл из преобразованного файла bat может быть запущен двойным щелчком. Он использует тот же интерфейс, что и предыдущий скрипт:
bat2exejs.bat example.bat example.exe
Я знаю, как конвертировать bat/cmd в exe вручную, убедитесь, что имя файла bat/cmd содержит только буквы и цифры. Откройте " Мастер IExpress" в качестве администратора.
- Выберите "Создать новый файл директивы самоизвлечения"
- Выберите "Извлечь файлы и запустить команду установки".
- Назовите пакет что-нибудь
- "Нет запроса" для "Подтверждение запроса"
- "Не отображать лицензию" для "Лицензионного соглашения"
- Нажмите "Добавить" для "Упакованных файлов", оттуда выберите файл bat/cmd
- Затем в текстовом поле "Установить программу" для "Установить программу для запуска" введите
cmd /c
с последующим полным именем файла bat/cmd (пример:emptyrecyclebin.bat
=>cmd /c emptyrecyclebin.bat
) - Оставьте "Команду после установки" как есть
- "Скрыто" для "Показать окно"
- "Нет сообщения" для "Готового сообщения"
- Нажмите "Обзор" и выберите, куда загрузить файл
- Включить "Скрыть файл извлечения анимации прогресса от пользователя"
- Отключить "Хранить файлы, используя длинное имя файла внутри пакета"
- Определенно "Нет перезагрузки" для "Настроить перезагрузку"
- Затем сохраните SED, если вы хотите перекомпилировать его быстрее
- Тогда создайте пакет! Окно команд должно быстро появиться и исчезнуть
- Перейдите к месту, где вы скачали исполняемый файл, и наслаждайтесь!
Все вышеперечисленные методы никоим образом не защищают ваш исходный код. Недавно я увидел в новостях пресс-релиз о новом компиляторе, не зависящем от CMD.exe. Я точно не знаю, как это работает, но он не создает временные файлы во время выполнения. https://www.prlog.org/12882479-the-worlds-first-true-compiler-for-batch-files.html
Вы также можете разработать простой exe-файл, который просто вызывает ваш bat-скрипт.
Например, вы могли бы написать один на C# (я не C#-Pro, это на самом деле моя первая программа, и я скопировал много из этого другого поста Stackru.):
using System;
using System.Diagnostics;
using System.Windows.Forms;
using System.IO;
class BatCaller {
static void Main() {
var batFile = System.Reflection.Assembly.GetEntryAssembly().Location.Replace(".exe", ".bat");
if (!File.Exists(batFile)) {
MessageBox.Show("The launch script could not be found.", "Critical error", MessageBoxButtons.OK, MessageBoxIcon.Error);
System.Environment.Exit(42);
}
var processInfo = new ProcessStartInfo("cmd.exe", "/c \"" + batFile + "\"");
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;
processInfo.RedirectStandardError = true;
processInfo.RedirectStandardOutput = true;
var process = Process.Start(processInfo);
process.OutputDataReceived += (object sender, DataReceivedEventArgs e) => Console.WriteLine("output>>" + e.Data);
process.BeginOutputReadLine();
process.ErrorDataReceived += (object sender, DataReceivedEventArgs e) => Console.WriteLine("error>>" + e.Data);
process.BeginErrorReadLine();
process.WaitForExit();
Console.WriteLine("ExitCode: {0}", process.ExitCode);
process.Close();
}
}
Если вы сохраните этот код выше в MySuperApp.cs рядом с MySuperApp.bat, а затем скомпилируете его с csc.exe /target:winexe MySuperApp.cs
(и, возможно, даже добавить /win32icon:MySuperApp.ico
чтобы добавить причудливый значок), он сгенерирует MySuperApp.exe.
Запуск MySuperApp.exe
вызовет MySuperApp.bat (bat-файл с тем же именем).
csc.exe
(должен?) присутствовать на каждом компьютере с Windows.
Различные версии Windows имеют разные эффекты для одних и тех же команд командного файла, а некоторые команды ограничены некоторыми системами Windows, например. findstr
а также shutdown
.
Кстати, Win 10 CMD не позволяет изменятьSETLOCAL
в командной строке. ОК для командных файлов.
См. По этой ссылке различные команды для перезапуска разных версий Windows:https://www.computerhope.com/issues/ch000321.htm
Поэтому, если бы вы скомпилировали сценарий в Win 98 и запустили в Win 8.1, вы бы получили неожиданные результаты, или сценарии могут даже не работать. См. Список команд здесь:https://www.ionos.com/digitalguide/server/know-how/windows-cmd-commands/
По этой причине для каждой версии Windows потребуется отдельный компилятор, предпочтительно, который будет выдавать двоичный код (общий), который можно запускать на максимально возможном количестве микросхем ЦП с одинаковыми наборами инструкций. Обходной путь, предлагаемый большинством программ, заключается в том, чтобы обернуть сценарий в исполняемый файл, который будет разворачивать и выполнять сценарий при открытии / запуске, например. Bat_To_Exe_Converter, Bat2Exe, BatchCompiler, iexpress или Winzip:https://support.winzip.com/hc/en-us/articles/115011794948-What-is-a-Self-Extracting-Zip-File-
Чтобы решить эту проблему переносимости, виртуальные машины стали более популярными, что привело к появлению Java и связанных скриптов.
Однако это все равно будет интерпретируемым кодом, а не таким быстрым, как скомпилированный код. Даже байт-код (промежуточный код) виртуальных машин все равно нужно компилировать, даже если он (JIT):https://aboullaite.me/understanding-jit-compiler-just-in-time-compiler/
Короче говоря, вы можете получить exe-файл, который будет содержать скрипт, который будет интерпретироваться командным процессором, но он не будет собственным исполняемым файлом, то есть он не будет работать без хоста операционной системой Windows.
Пакетный компилятор (http://batchcompile.com) - лучшее бесплатное решение для компиляции пакетных файлов. вы можете включить информацию о версии, информацию об авторских правах, значки, ресурсы и графику.
Я нашел этот ответ на суперпользователе.
Из двух я должен сказать, что конвертер bat в exe является лучшим. Это позволяет Icon добавлять и запускать вновь созданные.exe
с манифестом администратора, информацией о версиях, некоторыми встроенными примерами и редактором.
Скриншот графического интерфейса.
Кредит Рамми
Вот 2 бесплатные программы, которые я настоятельно рекомендую для создания EXE из командных файлов.
Вы можете использовать обе программы с простым графическим интерфейсом.
Bat To Exe Converter
поддерживает также команды CLI (\?
флаг для помощи). Базовый пример из документации:
Bat_To_Exe_Converter.exe -bat mybatfile.bat -save myprogram.exe -icon myicon