Gracefully trap error on start cmd - batch-file

On a cmd prompt or bat file, I issue the following:
start textpad myfile.txt and it works fine.
If the program textpad does not exist on the computer, then an error sound and a popup occurs which the OK button must be pushed.
I desire to trap this error so that I could do something like
start textpad myfile.txt || start notepad myfile.txt
where the || implies that if the start of textpad is not successful, then the start of notepad should occur. HOWEVER, I still get the error sound and requirement of hitting OK.
My intent is to avoid the sound and the requirement of any user intervention.
I have also tried the following bat approach below, to no avail.
start textpad
if not %ERRORLEVEL% == 0 GOTO END
start notepad
:END
Any help would be great.
thanks
ted

You can use the following little snippet to find out whether the program you intend to launch exists:
for %%x in (textpad.exe) do set temp=%%~$PATH:x
if [%temp%]==[] echo Didn't exist.
But may I suggest that you simply use
start foo.txt
instead of forcing a specific editor onto the user? File type associations are there for a reason.

I do not believe you will find a way to make that work. Perhaps look for the existence of textpad.exe on the machine? If you can predict what directory it would be loaded from, this should be pretty easy using IF EXIST.

There are some techniques to detect the presence of a specific tool, but this only works for command line tool, or with GUI applications also supporting command line options.
For these tricks, take a look at this page.

"/wait" parameter would do the trick for you..
START /wait NOTEPAD.EXE SOME.TXT
echo %ERRORLEVEL%
# This gives zero as output.
START /wait TEXTPAD.EXE SOME.TXT
echo %ERRORLEVEL%
# This gives non-zero output.

You probably already have an answer, but my over-sized ego has forced me to post my answer.
So, this should work.
start textpad 2> nul||start notepad
This will start notepad if the command start texpad fails, while also redirecting any error message you may get from the first command.

Related

Error "Invalid path 0 File(s) copied" using xcopy in batch file

I want to start with a little disclaimer:
I read this thread on a similar issue to mine, but it seems like the solution doesn't work. It might just be me not understanding it completely but here I am asking for clarification.
My goal is to copy a shortcut to the start menu programs folder conserving all of its attributes, icon and start in value. I thought making a copy would be simple but it seems like my brain can't understand anything today.
So here's the actual xcopy argument:
#echo off
xcopy "%~dp0\file.lnk" "%userprofile%\Start Menu\Programs\file.lnk\" /p /v /f
pause
I have tried every combination of adding/removing the file name, with/without the \ at the end and any combination of both... I also tried running the batch file as administrator just in case.
The #echo off is just a habit and the pause is to allow me to read any error messages that could pop up. I also put the extra arguments into the xcopy line to try to get more information. It doesn't seem to help me a lot though.
I'm starting to think the issue is completely isolated from the other thread.
As suggested by SomethingDark, changing the path from %userprofile%\Start Menu\Programs\ to %AppData%\Microsoft\Windows\Start Menu\Programs\ fixed my issue.

Opening project in VSCode using batch file

Disclaimer: I read this and this before, but it doesn't work as I want.
Description: I decided to create set of batch files for convenient way to run different projects in VSCode from desktop in one click(double-click). I want close cmd terminal after running a batch file, but terminal remains. I tried:
start code "C:\Users\MyUserName\path\to\my\project\directory"
and
cmd /c start code "C:\Users\MyUserName\path\to\my\project\directory"
It quickly runs command, runs code and opens my project, then, it seems to me, closes terminal and runs a new one in desktop directory.
I found solution with help of DavidPostill. This works fine for me:
start "" cmd /b /c code "C:\Users\MyUserName\path\to\my\project\directory" && exit 0
UPDATE:
There is a more simple way to run VSCode using command line interface:
cd path/to/my/project
code .
If anyone else comes across this in 2022, I found a solution that works great for me.
code "" "C:\path\to\folder\with\project" | exit
Also, below is my batch I made for a quick workspace that:
asks for a folder name, this will also be used as the project name
makes the vscode project
makes 2 text files, one for things I had to look up, and another for answers to my question
makes a png file called work.png that opens with paint for diagrams I might need for thinking through things
Lastly (the part I love the most) it CLOSES the command window once everything is opened!
Hope this helps someone like me who doesn't know everything about batch files!
#echo off &setlocal
set /p "folder=Enter the folder name to be created: "
md "%folder%" ||(pause &goto :eof)
cd %folder%
echo. > Things_I_had_to_look_up.txt
echo. > Answers.txt
dotnet new console
xcopy /s "C:\xPaintFileTemplate" "C:\Users\TBD\Documents\Program Work\%folder%"
start mspaint.exe Work.png
code "" "C:\Users\TBD\Documents\Program Work\%folder%" | exit
Rem not needed but to be safe
exit
The C:\xPaintFileTemplate is a folder in my C drive that contains only a png file named Work.png. The png file is blank, and sized to what I want mspaint to open with. If there are more files in that folder, it will copy all of them, so be careful with xcopy!
The Rem is a comment, saying the exit command doesn't seem to be required but I added it in anyways as I believe it is good practice.
Try using: start cmd /C code . :0 It should be able to close the cmd terminal. At least that worked for me on my Windows 10.
Another version:
start cmd /C code "C:\Users\MyUserName\path\to\my\project\directory" :0
Based on Blake Daugherty's answer, I found the first pair of double quotes seems unnecessary:
code "D:\proj\directory-1" | exit
code "D:\proj\directory-2" | exit
exit
None of the above worked for me; at worst one of the left-over CMD's needed its close button clicking three times before it would go away.
I tried the URL method and this worked just as I wanted: VSCode opened, and the cmd window went away; my batch file ("VSCode on project.bat") contains just one line:
start vscode://file/C:/path/to/project
or:
start "" "vscode://file/C:/path/to/project"
One line code:
code C:\Users\MyUserName\path\to\my\project\directory pause

Batch File Ending Prematurely

I have a batch file with the following commands (to set up a compiler):
del Yylex.java
jflex scanner.flex
del parser.java
java -jar java-cup-11a.jar parser.cup
However, for some reason, after the conclusion of jflex scanner.flex, the batch script ends and command prompt closes. If I just run that command separately, this does not happen. Does anyone know what's wrong?
Is jflex a batch file?
If so, try
CALL jflex ...
or
start /wait "" jflex ...
(well, actually - give it a whirl anyway, can't hurt...)
When bat is asked to run another batch, it merely transfers control to that other batch and has no idea of where to return. CALL or START gives it a ticket home...

To "Call" or "Not to Call" a batch file?

If from inside a bat file you called another batch file but still had a few remaining operations to complete, how can you make sure that the call to first bat file will after completion or error, will return to the file that called it in the first instance?
Example:
CD:\MyFolder\MyFiles
Mybatfile.bat
Copy afile toHere
or
CD:\MyFolder\MyFiles
CALL Mybatfile.bat
COPY afile toHere
What is the difference between using CALL or START or none of them at all? Would this have any impact on whether it would return for the results of the copy command or not?
As others have said, CALL is the normal way to call another bat file within a .bat and return to the caller.
However, all batch file processing will cease (control will not return to the caller) if the CALLed batch file has a fatal syntax error, or if the CALLed script terminates with EXIT without the /B option.
You can guarantee control will return to the caller (as long as the console window remains open of course) if you execute the 2nd script via the CMD command.
cmd /c "calledFile.bat"
But this has a limitation that the environment variables set by the called batch will not be preserved upon return.
I'm not aware of a good solution to guarantee return in all cases and preserve environment changes.
If you really need to preserve variables while using CMD, then you can have the "called" script write the variable changes to a temp file, and then have the caller read the temp file and re-establish the variables.
call is necessary for .bat or .cmd files, else the control will not return to the caller.
For exe files it isn't required.
Start isn't the same as call, it creates a new cmd.exe instance, so it can run a called batch file asynchronosly
The `CALL' statement was introduced in MS-DOS 3.3
It is used to call other batch files within a batch file, without aborting the execution of the calling batch file, and using the same environment for both batch files.
So in your case the solution is to use CALL
Okay, I actually didn't even really think about the fact that if you call a batch (regardless of the 'type', i.e. '.bat', or '.cmd') that it won't return if you don't use call.
I've been using call myself though for a different reason that I am actually pretty surprised that no one else has brought up. Maybe I missed it. MAYBE I'M THE ONLY ONE IN THE WORLD WHO KNOWS!! :O
Probably not, but I'm going to drop this knowledge off here because it's super useful.
If you use call you can use binary logic operators to decide how to proceed based on the ERRORLEVEL result. In fact, I always was flabbergasted on how && and || existed in DOS and COULDN'T be used this way. Well, that's why.
The easiest way to test this is to create a return.cmd with notepad, or from the command prompt like so:
c:\> type con >return.cmd
You will now notice the cursor goes down to the next line and hangs. Enter:
#exit /B %1
And then hit ENTER, and then CTRL-Z and that file will be created. Good! You may now feel free to try the following two examples:
call return.cmd 0 && echo Huzzah! A Complete Success! (Or cover up...)
call return.cmd 123 || echo Oops! Something happened. You can check ERRORLEVEL if you want the tinest amount of additional information possible.
So what? Well, run them again with the 0 and the 123 swapped and you should see that the messages DON'T print.
Maybe this multi-line example will make more sense. I use this all the time:
call return.cmd 0 && #(
echo Batch says it completed successfully^^!
) || #(
echo Batch completed, but returned a 'falsey' value of sort.
call echo The specific value returned was: %ERRORLEVEL%
)
(Note the 'call' in the || section before the second 'echo'. I believe this is how people got around not having delayed expansion back in the day. If you DO have delayed expansion enabled (via. setlocal EnableDelayedExpansion inside a batch OR launch a command prompt with cmd /v:on then you can just do !ERRORLEVEL!.)
... This is where I have to apologize and say if you have if ERRORLEVEL trauma in your past you should stop reading. I get it. Trust me. I thought about paying someone on fiverr to remotely type this for me, but for completeness sake I'm just going to take one for the team and mention that you can also do the following to check errorlevel:
if ERRORLEVEL 123 #echo QUICK! MOTHERS, COVER YOUR CHILDREN'S EYES! FINGERS ARE BEING UNDONE! :'(
If you've never typed that before then GOOD! You will live longer without having to read up why exactly you aren't getting the results you expect. Cruel is the word you're looking for, not 'quirky'.
The important part that I really want to get across however is that if you try this and DON'T use 'call' it will ALWAYS execute the 'true' branch. Try it for yourself!
If I'm missing something, or you know a better way to do this, please let me know. I love learning stuff like this!
Additional information I mentioned:
I have known for quite some time that you can put redirects BEFORE commands like so:
>nul echo. This won't be displayed!
But I accidentally discovered the other day by being a dumdum that you can apparently also do:
echo A B>file.txt C
And was REALLY surprised to find a file.txt which consisted of "A B C". It appears yo can place them ANYWHERE, even inside the command. I've never seen anyone do this, nor mention it, but I HAVE seen people mention that you can prefix a line with them.
Maybe it's a bug exclusive to Windows 10 or something. If you have another version and wanna try it out and let me know I'd be interested in what you find out.
Stay nerdy!

Jenkins always considers a build successful using batch/bat

I just joined a company that uses batch files to build a C++ project. The batch does all sorts of things (updates svn, which is now done by jenkins), creates build folders, deletes unnecessary files after building, copies library files to the build folder, etc.
My problem is Jenkins always considers the build successful, even when it´s not. The .bat file creates a file called errormake.txt when something goes wrong. How do I make jenkins read that and mark the build as a failure?
Also, is there any way I can find out the build folder Jenkins created from inside the .bat file (maybe send a variable when I call the batch file)?
This is the single line I'm currently using to call the .bat file:
call "C:\Source\BuildVersion\AppName\build_version.bat"
Edit: Also, this project is split up into several SVN repositories. %SVN_REVISION% is blank. How can I get the correct %SVN_REVISION% from the first repository (the main one)?
To answer each of your questions -
Jenkins always return "SUCCESS", even when the Job actually failed:
Jenkins sets the status of the Job, based on the return-code of the last command
that ran in each "Execute windows batch command" block.
If your last command is copy some.log D:,
Jenkins thinks everything is OK
(If the 'copy' command went fine...)
Use EXIT xx or EXIT /B xx, depending on your OS,
where 'xx' is some integer greater than zero.
How do I make Jenkins mark the build as a failure, based on a log-file:
Use the Text-finder Plugin, as mentioned by sdmythos_gr .
Is there any way I can find out the build folder Jenkins created:
There are a few parameters that are available as environment-variables
for each script that runs under Jenkins - see here for the list of those parameters:
Jenkins Environment Variables.
To your question:
%WORKSPACE% - The absolute path of the workspace
%BUILD_NUMBER% - The current build number, such as "153"
%BUILD_ID% - The current build id, such as "2005-08-22_23-59-59"
(YYYY-MM-DD_hh-mm-ss)
How can I get the correct %SVN_REVISION% from the first repository:
This answer is from the same link:
%SVN_REVISION% - For Subversion-based projects,
this variable contains the revision number of the module.
If you have more than one module specified, this won't be set.
Hope that helps
Jenkins use the windows error code to know whether a build failed or not.
You should return a value different from 0 when your build failed, with "exit /B 1" for example.
On "newer" versions of Windows (I tested on Server 2012 R2), put the following at the end of each Windows batch command:
#EXIT /b %ERRORLEVEL%
This will pass the error code that the cmd.exe received back to the caller (i.e. Jenkins). The "#" turns off echoing so you don't clutter up your log.
If you have multiple lines in the command and want to stop after the first failure, put the following after each line that you want to check (yes, this is not pretty):
#IF NOT %ERRORLEVEL% == 0 EXIT /b %ERRORLEVEL%
For example:
step1.exe
#IF NOT %ERRORLEVEL% == 0 EXIT /b %ERRORLEVEL%
step2.exe
#IF NOT %ERRORLEVEL% == 0 EXIT /b %ERRORLEVEL%
call "C:\Source\BuildVersion\AppName\build_version.bat"
#EXIT /b %ERRORLEVEL%
I'm also going to answer just part of your question.
There is a Text Finder plugin for Jenkins that you could use.
https://wiki.jenkins-ci.org/display/JENKINS/Text-finder+Plugin
You can mark the build as unstable or failed at the end of the build depending on the contents of a file or the console output.
Maybe this could help...
I know the question is quite older but may be useful to some people. To execute your bat file, instead of using following line,
call "C:\Source\BuildVersion\AppName\build_version.bat"
You can use below format,
<someRelativeOrAbsolutePath>\<.batFileName> <param1> <param2> <and so on>
Executing the command in this way inside Execute Windows Batch Command of Build section of Jenkins will use your last return code of the command. ${BUILD_STATUS} will depend on that. And you will not have to modify your script to return some condition based error codes.
As other users have stated your batch files should use "exit /B 1". Here is a trick to chain together your calls causing Jenkins to return a failure if one fails:
call a.bat &&^
echo "a success" &&^
call b.bat &&^
echo "b success"
"&&" denotes that the next action should only run on success (exit code 0). "^" lets us split the command into multiple lines. The downside to this approach is the build progress bar doesn't display accurately.

Resources