I have used iexpress to wrap a .bat file within an .EXE file.
The .bat file contains commands to install my project on Windows.
I followed all the steps and I got an .exe file, but when run it shows a finished msg but nothing is done. (no command inside the bat file is running).
#echo off
echo %DATE% >> "C:\Users\gaubansa\Desktop\my.txt"
echo %PATH% >> "C:\Users\gaubansa\Desktop\my.txt"
Cotnets of the .SED file:
[Version]
Class=IEXPRESS
SEDVersion=3
[Options]
PackagePurpose=InstallApp
ShowInstallProgramWindow=1
HideExtractAnimation=0
UseLongFileName=0
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=Write
DisplayLicense=
FinishMessage=ho gya
TargetName=C:\Users\gaubansa\Desktop\my.EXE
FriendlyName=Write
AppLaunched=cmd.exe /c my_personal.bat
PostInstallCmd=<None>
AdminQuietInstCmd=
UserQuietInstCmd=
FILE0="my_personal.bat"
[SourceFiles]
SourceFiles0=C:\Users\gaubansa\Desktop\
[SourceFiles0]
%FILE0%=
According to the Iexpress directive (.SED) file you posted, the problem is that you configured Iexpress to store file names in the package using short file names so your batch file my_personal.bat will be stored in the package using its short file name MY_PER~1.BAT but you have specified cmd /c my_personal.bat to run your batch file so cmd can not find my_personal.bat.
To resolve that choose the option Store files using Long File Name inside Package in Iexpress. Alternatively you can edit the SED file and change the directive UseLongFileName=0 to UseLongFileName=1 then in Iexpress GUI select Open existing Self Extraction Directive file
Some additional advise
Although your batch file name does not contain spaces or other special characters it is always a good practice to enclose the file name in quotes. So you should change AppLaunched=cmd.exe /c my_personal.bat to AppLaunched=cmd.exe /d /c "my_personal.bat"
The /d switch is optional, it is to prevent cmd from executing commands that may be present cmd's AutoRun registry settings. You can get more information about it by typing CMD /? at command prompt.
A safer option would be use AppLaunched=cmd.exe /d /s /c ""my_personal.bat"" so in future if you ever decide to repackage your batch file and pass some quoted parameter to it, you can do that without the risk of essential quotation marks being removed by cmd.
for example: cmd.exe /d /s /c ""my_personal.bat" "Quoted Param1" "Quoted Param2" UnquotedParam3"
There are many reasons to want to 'convert' a .bat to .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.
There are also many reasons to not want to use third party tools.
So what if you want to 'convert' a batch file to .exe without 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 .bat file and then call it )
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 IEXPRESS sed-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:
;#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=
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
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/.bat script 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):
#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).
I promise an upvote to every improvement over the .NET method :-)
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:
bat2exejs.bat example.bat example.exe
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.
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 quickly appear and disappear
Navigate to the place where you downloaded the exe to, and enjoy!
All of the above methods do not protect your source code in any way. I recently saw a press release in the news about a new compiler that does not depend on CMD.exe. I don't know exactly how it works, but it doesn't create temporary files at runtime.
https://www.prlog.org/12882479-the-worlds-first-true-compiler-for-batch-files.html
Using IEXPRESS makes a kind of SFX archive, which does not achieve the main goal of hiding the source code with passwords. All other "compilers" work on a similar principle - extract the script to a temporary folder and run it via cmd.exe. The press release claimed a real compilation, so I downloaded the trial version and wrote a primitive script to measure the speed:
#echo off
set startTime=%time%
set counter=0
:main_loop
echo %counter%
set /a counter=counter+1
if %counter% LEQ 10000 goto main_loop
echo Start Time: %startTime%
echo Finish Time: %time%
After compiling the code runs twice as fast and I haven't noticed any calls to cmd.exe in the Task Manager. In addition, I ran Process Monitor and saw no creation of temporary files while it was running. This leads me to believe that this compiler provides better protection for the source code.
You can also develop a simple exe, which just calls your bat-script.
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.):
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.ico to add a fancy icon) it will generate a MySuperApp.exe.
Launching MySuperApp.exe will call MySuperApp.bat (the bat-file with the same name).
csc.exe (should?) be present on every Windows machine.
Different versions of Windows has different effects for same batch file commands, and some commands are limited to some Windows systems eg. findstr and shutdown.
BTW, Win 10 CMD doesn't allow changes to SETLOCAL on command line. OK for batch files.
See this link for different commands for restarting different versions of 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/
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-
To solve this issue of portability, virtual machines have become more popular and hence the rise of Java & related scripts.
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/
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.
I am trying to add a new option to the context menu for folders in Windows. I have managed to add the option and specify its command as follows:
xcopy.exe "%0\*" "c:\Destination\" /EHY
This code is added to regedit.exe
I have a folder in the c: drive named Destination. I am trying to copy the folder that I right clicked to the Destination folder, without a command prompt window.
What is happening: xcopy is running and copying the content of the folder and in the foreground. Please help me with these two issues:
Run the xcopy command without showing a window.
Copy the folder to a new folder in Destination named after the copied folder.
Thank you.
The command that satisfies the two issues listed is at the very end. First, some notes of explanation.
When you add a shell command to the Windows Registry, you have several variables available to you (such as %1, %L, and %V). Now, you would like a new folder in Destination named after the copied folder. Parameter extensions (such as %~n1) can strip everything from the full path and give you the name of the directory leaf.
However, these are not available when using the shell command from the Windows Registry. The most straightforward way to get a plain directory name is to create a temporary batch script, run it, and delete the batch script afterwards.
The following will copy the selected directory as a sub-directory inside Destination:
cmd.exe /c echo #echo off>"C:\Destination\_tempxcopy.bat" & echo xcopy "%%~1\*" "C:\Destination\%~n1" /ECIQHY ^>nul>>"C:\Destination\_tempxcopy.bat" & call "C:\Destination\_tempxcopy.bat" "%1" & del "C:\Destination\_tempxcopy.bat"
This next part requires the use of a third-party utility.
The previous command will open a command window and leave it open as long as copying is in progress. To hide that window, use the tiny utility RunHiddenConsole
The following will copy the selected directory and hide the command window while copying:
"C:\Destination\RunHiddenConsole.exe" cmd.exe /c echo #echo off>"C:\Destination\_tempxcopy.bat" & echo xcopy "%%~1\*" "C:\Destination\%~n1" /ECIQHY ^>nul>>"C:\Destination\_tempxcopy.bat" & "C:\Destination\RunHiddenConsole.exe" /w "C:\Destination\_tempxcopy.bat" "%1" & del "C:\Destination\_tempxcopy.bat"
This could certainly be made more flexible and efficient, but the above command at least demonstrates the technique for accomplishing the task.
I am very new to Jenkins and want it to build a complete .exe. I set the Repository to a personal URL, now Jenkins do read all the files and copies everything to the Jenkins Workspace. My question is what do I insert into the "Execute Windows Batch Command" block in Jenkins so that it would Compile a NSIS script and store the Setup file in a output file. I have done research into Windows Batch Scripting but nothing that could truly help me in this struggle. If I am doing it all wrong I would love some advice to get me on the right track. Here are my current Jenkins codes to read and safe the files from the repository:
1st "Execute Batch Command"
COPY "C:\Program Files (x86)\Jenkins\jobs\Job_name\Path\*.*" "C:\Program Files (x86)\Jenkins\jobs\Job_Name\workspace\Output\Installs" /Y
2nd "Execute Batch Command"
del c:\inetpub\wwwroot\downloads\%SVN_REVISION%\*.* /s /f /q
rmdir "C:\inetpub\wwwroot\downloads\%SVN_REVISION%"
exit 0
3rd "Execute Batch Command"
MKDIR "C:\inetpub\wwwroot\downloads\%SVN_REVISION%"
4th "Execute Batch Command"
COPY "C:\Program Files (x86)\Jenkins\jobs\Job_Name\workspace\Output\Installs"
"c:\inetpub\wwwroot\downloads\%SVN_REVISION%" /Y
Now all I want Jenkins to do is open my .nsi script, compile and create the Setup File which then saves in an output folder.
Create new batch command with following:
path_to_NSIS_folder>\makensis.exe path_to_your_nsi_file
makensis.exe is a NSIS compiler and all it needs is path to the script file (.nsi).
When run the script is compiled and (if no errors) reslting setup.exe is created (the output can se set in .nsi file).
I just start to learn how to build batch file. ( on the windows 7 environment)
I want to build the batch file which is able to run .exe files sequentially .
Run batch files sequentially
I was trying to apply above idea but I am not really sure how to apply it
For example, there are three file on the D:/
In "D:/" there are three .exe files.
MyDriver.exe
YouDriver.exe
Mysoftware.exe
And I would like to build batch file which is running three exe files sequentially
Possible scenario is..
Run batch file
Run MyDriver.exe
MyDriver file's install GUI pops up and then user start to install Mydriver
Done with MyDriver.exe
Run YouDriver.exe
YouDirver file's install GUI pops up and then user start to install YouDriver
Done with YouDriver.exe
Run MySoftware.exe
MySofrware install interface pops up and then user start to install MySoftware
Done exit batch file.
I am not really sure if batch files can do it or not...
if it is impossible , is there any other options to build it ???
thanks
You actually don't need to do anything special to make this happen; batch files are synchronous by default, so execution of the batch file will pause when an executable is launched, and resume when it exits. Something as simple as this should do:
#echo off
REM "#echo off" prevents each line from being printed before execution,
REM and is optional
REM "REM" introduces a comment line
D:\MyDriver.exe
D:\YouDriver.exe
D:\MySoftware.exe
Of course, if you're interested in checking the return values of the programs, to see whether they succeeded or failed to install (assuming the installer provides that information), then things become slightly more complicated; if that's what you need, mention it in a comment, and I'll expand my answer accordingly.
This will start each file and wait for it to complete and then launch the next one.
#echo off
start "" /w /b "d:\MyDriver.exe"
start "" /w /b "d:\YouDriver.exe"
start "" /w /b "d:\Mysoftware.exe"
start MyDriver.exe
start YouDriver.exe
start MySoftware.exe
If you want the batch file in a different dir you would have to do:
cd D:\
start MyDriver.exe
start YouDriver.exe
start MySoftware.exe
If you want a more flexible system:
echo Welcome to EXE starter!
set /p dir = DIR:
set /p exe = EXE1:
set /p exe1 = EXE2:
set /p exe 2 = EXE3:
cd DIR
start exe
start exe1
start exe2
There you go!
To do it squentially:
call YouDriver.exe
call MeDriver.exe
call Mysoftware.exe
call will halt the batch file until program has closed.
Try and put it in the same directory of the files you want to run. If you can't, use cd C:\Directory\Name to change it to the directory where the MyDriver.exe file is. Then just do MyDriver.exe- you don't need a call or start statement.
MyDriver.exe
YouDriver.exe
MySoftware.exe
use cd at the start if you neeed to.