Jenkins cuts off parameter list inside batch script - windows

As part of my Jenkins pipeline I want to zip my output directory to a shared drive and I have a batch script that works wonderfully when running it through a shell, but when Jenkins runs it the file_names argument to 7zip goes missing and it zips the entire project folder instead.
The batch script looks as follows, where GGProjectName has a string value(no special characters) and CHANGESET is an integer
set path=D:\Data\Builds\%GGProjectName%\development
call "C:\Program Files\7-Zip\7z.exe" a -tzip %path%\%GGProjectName%-%CHANGESET%.zip .\Build\
Calling the batch script through a shell gives the following output with GGProjectName=ProjectName and CHANGESET=2:
E:\Jenkins\ProjectName\ProjectName_Main\workspace>set path=D:\Data\Builds\ProjectName\development
E:\Jenkins\ProjectName\ProjectName_Main\workspace>CALL "C:\Program Files\7-Zip\7z.exe" a -tzip D:\Data\Builds\ProjectName\development\ProjectName-2.zip E:\Jenkins\ProjectName\ProjectName_Main\workspace\Build\
7-Zip [64] 16.04 : Copyright (c) 1999-2016 Igor Pavlov : 2016-10-04
Scanning the drive:
23 folders, 439 files, 718413046 bytes (686 MiB)
Creating archive: D:\Data\Builds\ProjectName\development\ProjectName-2.zip
Items to compress: 462
Files read from disk: 439
Archive size: 137063321 bytes (131 MiB)
Everything is Ok
Getting Jenkins to run the same script gives the following output, with GGProjectName=ProjectName and CHANGESET=77:
17:04:21 E:\Jenkins\ProjectName\ProjectName_Main\workspace>set path=D:\Data\Builds\ProjectName\development
17:04:21
17:04:21 E:\Jenkins\ProjectName\ProjectName_Main\workspace>CALL "C:\Program Files\7-Zip\7z.exe" a -tzip D:\Data\Builds\ProjectName\development\ProjectName-77
17:05:57
17:05:57 7-Zip [64] 16.04 : Copyright (c) 1999-2016 Igor Pavlov : 2016-10-04
17:05:57
17:05:57 Scanning the drive:
17:05:57 856 folders, 14893 files, 2074486211 bytes (1979 MiB)
17:05:57
17:05:57 Creating archive: D:\Data\Builds\ProjectName\development\ProjectName-77.zip
17:05:57
17:05:57 Items to compress: 15749
17:05:57
17:05:57
17:05:57 Files read from disk: 14893
17:05:57 Archive size: 453305828 bytes (433 MiB)
17:05:57 Everything is Ok
I've identified the issue as Jenkins somehow cutting off the last argument to the call to 7z.exe, though I have no idea what causes it.
The Jenkins stage that runs the script is extremely straightforward so I have a hard time seeing that as the cause.
stage('Deploy') {
steps {
bat 'publish.bat'
}
}
I'm running Jenkins 2.204.2 on a Windows machine.

The main problem is most likely the string value assigned to environment variable CHANGESET which is not just the string 77, but the string 77 with a carriage return or a line-feed or carriage return + line-feed appended which results in a truncated command line on execution by Jenkins. So the source of this problem must be searched in code which defines the environment variable CHANGESET with a string not being only the number, but the number with a newline character.
GG_Victor wrote in a comment:
The carriage return seems to have been the issue and changing the assignment of CHANGESET to have a .trim() on the shell output in the jenkinsfile like so: env.CHANGESET = sh (...).trim() alleviated the issue.
But it would be even better to find out why the environment variable CHANGESET is defined with a string value with a carriage return appended to the number as that is the real source of the issue.
Another issue with the batch code is the redefinition of the predefined environment variable PATH with a string being a single folder path. Please take a look on What is the reason for "X is not recognized as an internal or external command, operable program or batch file"? You should know after reading the long answer from top to bottom why path should not be used as name of a local environment variable. Better would be FolderPath or ProjectPath or ArchivePath instead of path.
So the first line should be for example:
set "ArchivePath=D:\Data\Builds\%GGProjectName%\development"
The usage of " as done here is highly recommended. The reason is described in my answer on:
Why is no string output with 'echo %var%' after using 'set var = text' on command line?
The command CALL is needed only to call a batch file from within a batch file. It is not needed to run an executable from within a batch file. The Windows command processor halts the batch file execution until the started executable terminated itself. So the batch file execution is in your case not continued by cmd.exe until the started 7z.exe finished creating the archive file and terminated with exit code returned back to Windows command processor which assigns it to ERRORLEVEL for evaluation by one of the next commands.
This behavior on starting a console or GUI executable from within a batch file can be seen easily by creating a batch file with following five lines and execute it with a double click:
#echo off
echo Run Notepad.
%SystemRoot%\Notepad.exe
echo Notepad terminated.
pause
The Windows command processor outputs Run Notepad. and starts next Windows Notepad. The console window shows just Run Notepad. as long as the graphical window of Notepad is open because of cmd.exe waits for termination of Windows Notepad. Once Windows Notepad is exited by the user, the Windows command processor continues and outputs next the line Notepad terminated. Last the command execution is paused once more because of command PAUSE to give the user the possibility to see that the batch file execution continued after Notepad termination.
This behavior on starting an executable from within a batch file is different to starting an executable from within a command prompt window. Windows command processor does not wait for termination of the started executable if a user opens a command prompt, enters %SystemRoot%\Notepad.exe and hits key RETURN or ENTER to run Windows Notepad. The user can in this case immediately enter and execute the next command after switching from still opened Notepad window to the Windows command prompt window.
So for the second line should be used:
"C:\Program Files\7-Zip\7z.exe" a -bd -tzip -y -- "%ArchivePath%\%GGProjectName%-%CHANGESET%.zip" ".\Build\"
The double quotes are highly recommended again, especially on full qualified archive file name containing - after a space to avoid getting the rest interpreted by mistake as switch by 7z.exe or on full qualified file name containing a space or one of these characters &()[]{}^=;!'+,`~. It is best to always enclose file/folder names in double quotes even on not being really necessary.
The three additional switches -bd, -y and -- are described in help of 7-Zip.

Related

Trying to open programs with bat file but always comes back invalid

I am a streamer and I need a few programs to stream. It's annoying to open all of them so I tried putting them in a batch file. I looked up the process and followed it,but every time I run the batch file it comes back invalid.
This is what my batch file looks like:
#echo off
cd C:\Program Files "(x86)\obs-studio\bin\64bit"
start obs64.exe
#echo off
cd "C:\Program Files\HexChat"
start hexchat.exe
#echo off
cd "C:\Program Files (x86)\Nightbot"
start nightbot.exe
exit
Cmd gives me an error saying it cannot find the file. When I put this into cmd by itself it opens the program.
Also is there a way to add applications from chrome to the file?
Open a command prompt window and run from within this window start /? which outputs the help for this command and explaining all options.
Following batch file most likely works:
#echo off
start "" "%ProgramFiles(x86)%\obs-studio\bin\64bit\obs64.exe"
start "" "%ProgramFiles%\HexChat\hexchat.exe"
start "" "%ProgramFiles(x86)%\Nightbot\nightbot.exe"
This batch file starts the three applications with current directory on execution of the batch file being also the current directory for the 3 started applications.
But the following batch file should be used if it is really necessary that each application is started with the application's directory as current directory:
#echo off
start "" /D"%ProgramFiles(x86)%\obs-studio\bin\64bit" obs64.exe
start "" /D"%ProgramFiles%\HexChat" hexchat.exe
start "" /D"%ProgramFiles(x86)%\Nightbot" nightbot.exe
With parameter /D and path of application's folder the Start In directory is set first like when using command CD. So for example hexchat.exe is started with current directory being C:\Program Files\HexChat for this application.
The two double quotes after command START are necessary as this command interprets first double quoted string as title for the process. By using "" an empty title string is explicitly specified resulting in rest of command line being correct interpreted as expected. I suppose those three applications are all GUI applications and not console applications and therefore a real title string being useful on running a console application in an new command process for the console window is not really necessary.
%ProgramFiles% references the predefined environment variable ProgramFiles containing path to standard program files folder for 64-bit applications on 64-bit Windows when batch file is started with 64-bit cmd.exe as default on 64-bit Windows and is replaced by Windows command interpreter before execution of the command line on your Windows computer by C:\Program Files.
%ProgramFiles(x86)% references the predefined environment variable ProgramFiles(x86) containing always path to standard program files folder for 32-bit applications on 64-bit Windows and is replaced by Windows command interpreter before execution of the command line on your Windows computer by C:\Program Files (x86).
It is of course also possible to use the real paths in your computer instead of the environment variable references if this batch file is never shared with other people.
Extra hint:
Run in a command prompt window the command you want to use with /? as parameter to get displayed the help for this command. Other sources for help on commands and predefined environment variables displayed all on running in a command prompt window set are:
SS64.com - A-Z index of the Windows CMD command line
Microsoft's command-line reference
Windows Environment Variables and WOW64 Implementation Details

Problems Executing Powershell from .cmd file

I am attempting to run a build task from a .cmd file where Powershell extracts a zip file, which helps bypass a problem with Visual Studio's limit on the number of directory characters. However, I am having problems getting the Powershell command to execute correctly. I've tried a number of variations with the quotations, and I either get a termination error, or the Powershell command outputs as a string with the zip file not extracted. Below is an example of my current .cmd file:
//%1% is a passed in command line argument for the absolute path, e.g. C:\path\to\dir
set Source=%1%directory.zip
set Destination=%1%directory
powershell -Command $pscmd = '{Add-Type -assembly "system.io.compression.filesystem";[io.compression.zipfile]::ExtractToDirectory("%Source%", "%Destination%");}'; Write-Host $pscmd;
I'm very open to a number of variations that can get this to work, provided that this task runs on the command line, uses Powershell, and can be executed from a .cmd file, which is triggered by our app's build process. I'll be happy to provide additional information if needed. Thanks!
This was a strange one. Your code above has some sort of hidden character in it. I took the code and opened it in notepad, saved as ANSI, and when you type it to command line or open it again in a new instance of notepad you can see the error.
Neither add-type nor ExtractToDirectory give output, so I removed your pscmd var.
I would open your existing script, save as ansi as a new file name, delete the original, rename the new one back to the original name.
Here is what I came up with to troubleshoot your script, and it works on my machine.
I named my script L:\util\unzip.cmd
setlocal
//%1% is a passed in command line argument for the absolute path, e.g. C:\path\to\dir
set _Source='%1\directory.zip'
set _Destination='%1\directory'
echo _Source=%_Source%
echo _Destination=%_Destination%
set _c1=Add-Type -assembly system.io.compression.filesystem;
set _c2=[io.compression.zipfile]::ExtractToDirectory(%_Source%, %_Destination%)
echo _c1=%_c1%
echo _c2=%_c2%
set _Command=^& {%_c1% %_c2%};
: to echo, use double quotes or cmd thinks text after & is another command
echo _Command="%_Command%"
pause
powershell -Command "%_Command%"
endlocal
I ran it like this, and it worked: unzip.cmd L:\util
I'll bet this this info, you are good to go.

Build output from Visual Studio 2010 external tools in output window

I run a batch file as an external tool (by adding it in Tools->External tools) in VS2010 (I've checked the "Use Output Window" option). This batch file performs compilation as in VS command prompt. The project that I'm working on has makefiles for various folders, so I use the mk command to build.
In the batch file, I set up the VS environment and then run the following commands:
cd $directoryWhichContainsFileToBuild
mk
cd main //This directory contains the executable that is to be built
mk
I see the output of the first mk in the Output window but after that it just hangs. I also tried to use an echo after the first mk but even that doesn't get printed in the output window (the ones before it can be seen).
Somewhere I read that there is an issue with VS 2010 output window where it hangs after showing some output, although I couldn't really be sure that that is what's the issue here.
Do I need to enable some other VS setting? Has anybody else encountered this issue?
Thanks.
Update: I unchecked the "Use Output Window" and "Close on exit" option, and I see an extra statement: "Press any key to continue". On doing that however, their is no further processing of the batch file.
Update2: Got it to work by prefixing mk with "call".
Thanks all who tried.
It is always good in batch files to specify executables with full path and file extension instead of just the file name. This avoids often lots of problems.
Here was just mk used instead of mk.bat. Therefore on every compile the command line processor cmd.exe searches for mk.* and then checks if any of the found files have an extension listed in environment variable PATHEXT. The order of file extensions separated by a semicolon in PATHEXT defines the order of execution in case of a directory contains multiple mk.* files.
If a command being specified in a batch file not being an internal command of cmd.exe without path, command line processor searches first for a file with given name in current working directory. This is often one more cause of error. What is the current working directory on execution of the batch file?
Next if no file to execute can be found in current working directory, the command line processor searches in all folders being listed in environment variable PATH separated by semicolons.
So specifying in batch files edited only rarely an external application or another batch file with full path, file name and file extension, in double quotes if necessary because of 1 or more spaces in path or file name, helps command line processor to more quickly execute that application or batch file and avoids problems because of executable not found (unknown command).
Sure, when typing commands in a command prompt window, nobody wants to enter the executables with full path, name and extension. But for batch files it is always good to be not lazy and type files to be executed with full path and extension.
TripeHound has given already the explanation why the observed behavior occurred here.
If a batch file is executed from another batch file without using command call, the command line processor continues batch execution in the other batch file and does never come back. In a C/C++ program this is like using goto with the difference that parameters can be passed to the batch file containing the further commands to be executed next.
But running from within a batch file another batch file with call results in continuation of execution below the line calling the other batch file once the other batch file reaches end, except command exit is used in the called batch file without parameter /B.
So the solution here is using:
cd /D "Directory\Which\Contains\File\To\Build"
call "Path\Containing\Batch\File\To\Build\mk.bat"
rem With mk.bat not changing current working directory change working
rem directory to the directory containing the executable to be built.
cd main
call "Path\Containing\Batch\File\To\Build\mk.bat"
BTW: exit exits command processor, exit /B exits just current batch file. I'll give you three guesses why the parameter is B and not a different letter. Yes, B is the first letter of batch.
Writing as a separate answer instead of an update in the question itself as many readers see the header and skim to the answer: got it to work by prefixing mk with "call". (#TripleHound has also posted the conceptual reason for it in the comment above.)

Run an input file using an exe file with cmd

I am using Windows 7
How can i run an input file (text file of commands) in an exe progam in CMD please.
Using other questions on the site, i have tried:
CMD /c ""C:/Program Files/Mplus/Mpluswin.exe" "C:/Users/jj/Desktop/mplus/test_mplus.inp""
which opens the input file in the program but does not run it
and this, which opens the program, but not the script
CMD /c "C:/Program Files/Mplus/Mpluswin.exe" < "C:/Users/jj/Desktop/mplus/test_mplus.inp"
Does this depend on the exe program?
Edit:
At present, the first command above launches the exe program and opens the text file within it (this is a file of program specific commands that will read in data, run calculations and output automatically). I can then run the commands in the exe program that has been opened (by selecting run in a menu) . But, I would like to pass the file to the exe program and it to be run automatically, ideally in the background. I am not sure of the correct terminology to use, so sorry if my description is unclear.
I've just noticed that you enclosed the entire term in an extra set of double quotes, and used linux forward slashes - try this batch file and also see if there is any error message on the console.
#echo off
cd /d "%userprofile%\Desktop\mplus"
"C:\Program Files\Mplus\Mpluswin.exe" "test_mplus.inp"
echo mplus was launched
pause

help with windows batch scripting basics - execution and calling a separate executable within the script

Newbie to windows scripting. I need help running the .bat file on the command line so I can test it.
I used Text Document as my editor to create the file (opens up also as Notepad).
I performed file "save as" (ALL FILES). If I open up cmd, I can see the file has a .txt extension (myfile.bat.txt). So if I just type in cmd myfile.bat.txt the editor opens. I am not sure how to execute this correctly.
As for the logic in my batch script, I am basically logging into a remote directory (already created the net mount) and now I want to:
run an executeable file
rename some files.
With some research, I written this so far. I have saved it as a .bat file
# echo off
echo This is a batch file to run an executable and rename some files
pause
--run executable file here, just don't know how to do it
x:
cd x:
rename fileA fileB
Any help, good tips/practice would be great. Thanks.
Type in this command in cmd window:
rename myfile.bat.txt myfile.bat
Now you can run the script by simply invoking:
myfile.bat
or
myfile
(provided there's no myfile.exe or myfile.com in the same directory).
If you need to edit the script further, you can either right click it in Explorer and choose Edit or call the editor from the command window:
notepad myfile.bat
To call a program from the script, simply add its name, if it's in the current directory:
someprogram.exe
or the name with the path, if it's somewhere else:
directory\program.exe
or
d:\directory\program.exe
If the name or the path contain spaces, be sure to enclose the entire name & path string in double quotes:
"d:\directory\program name.exe"
you can just type the full name of the program
eg
"c:\program dir\program.exe"
or you can add the program directory to your path environment variable
set PATH=%PATH%;"c:\program dir"
and just type the program name
program
you can also edit your PATH variable in windows http://support.microsoft.com/kb/310519
NOTE: When you save the file in notepad, you want to save it as filename.BAT and select All Files from the second dropdown. If you don't it still gets saved as a .TXT.
A couple of command to consider:
CSCRIPT cscript /? in CMD
START http://ss64.com/nt/start.html
If you're doing say a VBSCRIPT use CSCRIPT to start it. If you're trying to execute another BATCH script or an EXE, use START

Resources