.net 如何在没有第三方工具的情况下将 .bat 文件“转换”为 .exe?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28174386/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can a .bat file be 'converted' to .exe without third party tools?
提问by npocmaka
There are many reasons to want to 'convert' a .batto .exe- to hide/obfuscate implementation, passwords, path to resources , to create a service from batch file ... and mainly to make your work to look more complicated and important than it really is.
有很多原因想要“转换”.bat到.exe- 隐藏/混淆实现,密码,资源路径,从批处理文件创建服务......主要是为了让您的工作看起来比实际更复杂和重要是。
There are also many reasons to not want to use third party tools.
不想使用第三方工具的原因也很多。
So what if you want to 'convert' a batch file to .exewithout external software?
(convert is in quotes because I don't think there's really way to compile a batch file to executable. There are too many abusive twisty techniques and bugs used extensively and all the tools that I know in fact create a temporary .batfile and then call it )
那么,如果您想在.exe没有外部软件的情况下将批处理文件“转换”呢?(convert 用引号引起来,因为我认为没有真正的方法可以将批处理文件编译为可执行文件。有太多滥用的扭曲技术和错误被广泛使用,我知道的所有工具实际上都创建了一个临时.bat文件然后调用它)
回答by npocmaka
One very obvious approach is to use IEXPRESS- the ancient built-in tool that creates self-extracting packages and is capable to execute post extraction commands. So here's IEXPRESSsed-directive/.bat file that creates a self-extracting .exe with packed .bat. It accepts two arguments - the .bat file you want to convert and the target executable:
一种非常明显的方法是使用IEXPRESS——一种古老的内置工具,可创建自解压包并能够执行解压后命令。所以这里是 IEXPRESS sed-directive/.bat 文件,它创建了一个带有打包 .bat 的自解压 .exe。它接受两个参数 - 要转换的 .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%exe.sed" >nul
;(echo()>>"%temp%exe.sed"
;(echo(AppLaunched=cmd.exe /c "%bat_name%")>>"%temp%exe.sed"
;(echo(TargetName=%target.exe%)>>"%temp%exe.sed"
;(echo(FILE0="%bat_name%")>>"%temp%exe.sed"
;(echo([SourceFiles])>>"%temp%exe.sed"
;(echo(SourceFiles0=%bat_dir%)>>"%temp%exe.sed"
;(echo([SourceFiles0])>>"%temp%exe.sed"
;(echo(%%FILE0%%=)>>"%temp%exe.sed"
;iexpress /n /q /m %temp%exe.sed
;del /q /f "%temp%exe.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=
example:
例子:
bat2exeIEXP.bat myBatFile.bat MyExecutable.exe
This should work practically on every Windows machine out there but has one major limitation - you cannot pass arguments to the created .exe file
这实际上应该适用于每台 Windows 机器,但有一个主要限制 - 您不能将参数传递给创建的 .exe 文件
So one other possible approach is to look at the .NET compilers (again should be available on almost every win machine).I've choose Jscript.net.
This is a hybrid jscript.net/.batscript that will read the .batch file content.Will create another jscript.net with the .bat file content and after the compilation will create a new bat file int the temp folder and will call it.And will accept command line arguments.(explained might look complex but in fact it's simple):
所以另一种可能的方法是查看 .NET 编译器(同样应该在几乎每台 win 机器上都可用)。我选择了Jscript.net。这是一个混合jscript.net/.bat脚本,它将读取 .batch 文件内容。将使用 .bat 文件内容创建另一个 jscript.net,编译后将在临时文件夹中创建一个新的 bat 文件并调用它。并将接受命令行参数。(解释可能看起来很复杂,但实际上很简单):
@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);
It's rather a POC , but .NET System.Diagnostics and System.IO libraries are powerful enough to add features like hidden start , enctiption and etc.You can check also jsc.exe compiling options to see what else is capable of (like adding resources).
它更像是一个 POC ,但 .NET System.Diagnostics 和 System.IO 库足够强大,可以添加隐藏启动、加密等功能。您还可以检查 jsc.exe 编译选项以查看其他功能(例如添加资源)。
I promise an upvote to every improvement over the .NET method :-)
我保证对 .NET 方法的每一项改进都给予支持 :-)
UPDATE:the second script has been changed and now the exe from the converted bat file can be started with double click.It uses the same interface as previous script:
更新:第二个脚本已更改,现在可以通过双击启动转换后的 bat 文件中的 exe。它使用与前一个脚本相同的界面:
bat2exejs.bat example.bat example.exe
回答by TheRealSuicune
I do know how to convert bat/cmd to exe manually, make sure the bat/cmd filename contains just letters, and numbers. Open 'IExpress Wizard' as admin.
我知道如何手动将 bat/cmd 转换为 exe,确保 bat/cmd 文件名只包含字母和数字。以管理员身份打开“ IExpress 向导”。
- Select 'Create new Self Extraction Directive file'
- Select 'Extract files and run an installation command'
- Name the package anything
- 'No prompt' for 'Confirmation prompt'
- 'Do not display a license' for 'License agreement'
- Click 'Add' for the 'Packaged files', from there select the bat/cmd file
- Then in 'Install Program' text box for 'Install Program to Launch', type
cmd /c, followed by the full name of the bat/cmd file, (example:emptyrecyclebin.bat=>cmd /c emptyrecyclebin.bat) - Leave the 'Post Install Command' as is
- 'Hidden' for 'Show window'
- 'No message' for 'Finished message'
- Click 'Browse', and select where to download the exe to
- Enable 'Hide File Extracting Progress Animation from User'
- Disable 'Store files using Long File Name inside Package'
- Definitely 'No restart' for 'Configure restart'
- Then save SED if you want to re-compile it quicker later
- Then create the package!A command window should quicklyappear and disappear
- Navigate to the place where you downloaded the exe to, andenjoy!
- 选择“创建新的自解压指令文件”
- 选择“提取文件并运行安装命令”
- 将包命名为任意
- “确认提示”的“无提示”
- “许可协议”的“不显示许可”
- 单击“打包文件”的“添加”,从那里选择 bat/cmd 文件
- 然后在“安装要启动的程序”的“安装程序”文本框中,键入
cmd /c,后跟 bat/cmd 文件的全名,(例如:emptyrecyclebin.bat=>cmd /c emptyrecyclebin.bat) - 保持“安装后命令”不变
- “隐藏”为“显示窗口”
- “已完成消息”为“无消息”
- 单击“浏览”,然后选择将 exe 下载到的位置
- 启用“隐藏来自用户的文件提取进度动画”
- 禁用“在包内使用长文件名存储文件”
- “配置重启”绝对是“不重启”
- 如果您想稍后重新编译它,请保存 SED
- 然后创建包!命令窗口应该快速出现和消失
- 导航到您下载 exe 的位置,然后享受吧!
回答by Itchy
You can also develop a simple exe, which just calls your bat-script.
您还可以开发一个简单的 exe,它只会调用您的 bat 脚本。
For example you could write one in C# (I'm no C#-Pro, this is actually my first program and I copied lots of it from this other Stackoverflow post.):
例如,你可以用 C# 编写一个(我不是 C#-Pro,这实际上是我的第一个程序,我从另一个 Stackoverflow 帖子中复制了很多。):
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();
}
}
If you store this code above to MySuperApp.cs just next to MySuperApp.bat and then compile it with csc.exe /target:winexe MySuperApp.cs(and maybe even add /win32icon:MySuperApp.icoto add a fancy icon) it will generate a MySuperApp.exe.
如果您将上面的代码存储到 MySuperApp.cs 中,就在 MySuperApp.bat 旁边,然后使用csc.exe /target:winexe MySuperApp.cs(甚至可能添加/win32icon:MySuperApp.ico以添加精美图标)进行编译,它将生成一个 MySuperApp.exe。
Launching MySuperApp.exewill call MySuperApp.bat (the bat-file with the same name).
启动MySuperApp.exe将调用 MySuperApp.bat(具有相同名称的 bat 文件)。
csc.exe(should?) be present on every Windows machine.
csc.exe(应该?)存在于每台 Windows 机器上。
回答by Zimba
Different versions of Windows has different effects for same batch file commands, and some commands are limited to some Windows systems eg. findstrand shutdown.
BTW, Win 10 CMD doesn't allow changes to SETLOCALon command line. OK for batch files.
不同版本的 Windows 对同一个批处理文件命令有不同的效果,有些命令仅限于某些 Windows 系统,例如。findstr和shutdown。
顺便说一句,Win 10 CMD 不允许更改SETLOCAL命令行。确定批处理文件。
See this link for different commands for restarting different versions of windows: https://www.computerhope.com/issues/ch000321.htm
有关重新启动不同版本 Windows 的不同命令,请参阅此链接:https: //www.computerhope.com/issues/ch000321.htm
So if you were to compile a script on Win 98, and run on Win 8.1, you'd get unexpected results or scripts may not even work. See list of commands here: https://www.ionos.com/digitalguide/server/know-how/windows-cmd-commands/
因此,如果您要在 Win 98 上编译脚本,然后在 Win 8.1 上运行,您会得到意想不到的结果,或者脚本甚至可能无法运行。在此处查看命令列表:https: //www.ionos.com/digitalguide/server/know-how/windows-cmd-commands/
For this reason, one would need a different compiler on each version of Windows, preferably which would spit out binary code (generic) that can be run on as many CPU chips as possible, with same instruction sets. A workaround offered by most programs is to wrap the script in an exe file that would unwrap and execute the script when opened/run eg. Bat_To_Exe_Converter, Bat2Exe, BatchCompiler, iexpress or Winzip: https://support.winzip.com/hc/en-us/articles/115011794948-What-is-a-Self-Extracting-Zip-File-
出于这个原因,每个版本的 Windows 都需要一个不同的编译器,最好能输出二进制代码(通用),可以在尽可能多的 CPU 芯片上运行,具有相同的指令集。大多数程序提供的解决方法是将脚本包装在一个 exe 文件中,该文件将在打开/运行时解包并执行脚本。Bat_To_Exe_Converter、Bat2Exe、BatchCompiler、iexpress 或 Winzip:https: //support.winzip.com/hc/en-us/articles/115011794948-What-is-a-Self-Extracting-Zip-File-
To solve this issue of portability, virtual machines have become more popular and hence the rise of Java & related scripts.
为了解决这个可移植性问题,虚拟机变得越来越流行,因此 Java 和相关脚本的兴起。
This however, would still be intepreted code, and not as fast as compiled code. Even byte code (intermediate code) from virtual machines still need to be compiled, even if it's (JIT): https://aboullaite.me/understanding-jit-compiler-just-in-time-compiler/
然而,这仍然是解释代码,不像编译代码那么快。即使来自虚拟机的字节码(中间代码)仍然需要编译,即使它是(JIT):https: //aboullaite.me/understanding-jit-compiler-just-in-time-compiler/
In short, you can get an exe file which would contain a script that would be intepreted by the command processor, but it won't be a native executable file, meaning it won't run without a host by the Windows operating system.
简而言之,您可以获得一个 exe 文件,其中包含将由命令处理器解释的脚本,但它不会是本机可执行文件,这意味着它不会在没有主机的情况下由 Windows 操作系统运行。
回答by Ste
I found this answer on superuser.
Out of the two I must say that bat to exe converter is the best. It allows Icon adding and running the newly created .exewith an admin manifest, versioning info, some built in examples and an editor also.
在这两者中,我必须说 bat 到 exe 转换器是最好的。它允许 Icon 添加和运行新创建.exe的管理清单、版本信息、一些内置示例和编辑器。
Screenshot of the GUI.
GUI 的屏幕截图。
Credit to rammi
归功于 rammi
Here are 2 free programs that I highly recommend for creating EXE's out of batch files
这是我强烈推荐用于从批处理文件中创建 EXE 的 2 个免费程序
You can use both programs with simple GUI.
您可以通过简单的 GUI 使用这两个程序。
Bat To Exe Convertersupports also CLI commands (\?flag for help). Basic example from documentation:
Bat To Exe Converter还支持 CLI 命令(\?帮助标志)。文档中的基本示例:
Bat_To_Exe_Converter.exe -bat mybatfile.bat -save myprogram.exe -icon myicon


