So, how I have it done right now, is that it that it calls another bat file to update it, and then that batch file updates, and sets %ERRORLEVEL% to 1. At the start of the original program, it checks if errorlevel is 1, if yes, it goes to the main menu, but right now, it doesn't call the update file, it just goes to the menu. This is my code
Main program
IF %errorlevel% EQU 1 goto begin
call updater.bat
:begin
echo MENU
Updater
set=errorlevel 1
wget (updatelink here)
call mainprogram.bat
Right now, sometimes it works, sometimes it doesn't, which leads me to believe that some command is somehow increasing the errorlevel, but the only code before the errorlevel check is
#echo off
color 0f
cls
set currentver=v0.5.6
(check code)IF %errorlevel% EQU 1 goto begin
https://code.google.com/p/flashcart-helper/source/browse/trunk/0.6/FlashcartHelperRobocopy.bat
Here is what I have right now.
Don't play around with errorlevel. It's an internal variable. At the start of a batch, errorlevel will be 0 because all you've done is set a local variable. This will almost always ( never say never ) succeed. Also, if errorlevel is 1, and I'm reading this correctly you also seem to have an infinite loop? From what I understand of what you've said your batches are like this:
Main
#echo off
color 0f
cls
set currentver=v0.5.6
IF %errorlevel% EQU 1 goto begin
call updater.bat
:begin
echo MENU
Updater
set=errorlevel 1
wget (updatelink here)
call mainprogram.bat
As errorlevel get's overwritten each time you do anything you're asking for trouble. Change %errorlevel% to %error% and it should solve your problems. As it's a local environment variable it should also be passed between batch files. Just be careful not to use error elsewhere.
Here is a solution using Dropbox Public Folders and no wget. It uses PowerShell that in on Win7+ machines.
Update the below https://dl.dropboxusercontent.com/u/12345678/ url with your own.
It auto creates a .conf file for configuration.
Set __deploy_mode to 1 for the file on dropbox so the version file can be updated but the script not accidentally executed.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET time_start=%time%
SET time_choice_wait=20
SET script_ver=1.00
SET script_name=%~n0
SET server_url=https://dl.dropboxusercontent.com/u/12345678/
SET script_name_bat=%~dp0%script_name%.bat
SET script_name_cfg=%~dp0%script_name%.conf
SET script_name_latest_ver=%~dp0%script_name%.latest.ver
ECHO %script_name% v%script_ver%
ECHO %script_ver% > %script_name%.current.ver
IF NOT EXIST "%script_name_cfg%" CALL :SCRIPT_MISSING_CFG
FOR /f "delims=" %%x IN (%script_name%.conf) DO (SET "%%x")
IF %__deploy_mode% EQU 1 GOTO :EOF
IF %auto_update_compare% EQU 1 CALL :SCRIPT_COMPARE_VER
:SCRIPT_MAIN
REM =======================================
REM === EDIT BELOW THIS LINE ==
REM TODO Add main content
ECHO.
ECHO Waiting for content...
REM === EDIT ABOVE THIS LINE ==
REM =======================================
GOTO END
:SCRIPT_MISSING_CFG
ECHO Creating new %script_name%.conf file...
ECHO __deploy_mode=0 > "%script_name_cfg%"
ECHO repository_base_url=%server_url% >> "%script_name_cfg%"
ECHO auto_update_compare=1 >> "%script_name_cfg%"
ECHO auto_update_download=1 >> "%script_name_cfg%"
ECHO Update %script_name%.conf as needed, then save and close to continue.
ECHO Waiting for notepad to close...
NOTEPAD "%script_name_cfg%"
GOTO :EOF
:SCRIPT_COMPARE_VER
ECHO Please wait while script versions are compared...
Powershell -command "& { (New-Object Net.WebClient).DownloadFile('%server_url%%script_name%.current.ver', '%script_name_latest_ver%') }"
IF NOT EXIST "%script_name_latest_ver%" GOTO END
SET /p script_latest_ver= < "%script_name_latest_ver%"
IF %script_ver% EQU %script_latest_ver% CALL :SCRIPT_COMPARE_VER_SAME
IF %script_ver% NEQ %script_latest_ver% CALL :SCRIPT_COMPARE_VER_DIFF
GOTO :EOF
:SCRIPT_COMPARE_VER_SAME
ECHO Versions are both %script_name% v%script_ver%
GOTO :EOF
:SCRIPT_COMPARE_VER_DIFF
ECHO Current Version:%script_ver% ^| Server Version:%script_latest_ver%
IF %auto_update_download% EQU 1 GOTO SCRIPT_DOWNLOAD_SCRIPT
ECHO.
ECHO Would you like to download the latest %script_name% v%script_latest_ver%?
ECHO Defaulting to N in %time_choice_wait% seconds...
CHOICE /C YN /T %time_choice_wait% /D N
IF ERRORLEVEL 2 GOTO SCRIPT_DOWNLOAD_NOTHING
IF ERRORLEVEL 1 GOTO SCRIPT_DOWNLOAD_SCRIPT
IF ERRORLEVEL 0 GOTO SCRIPT_DOWNLOAD_NOTHING
:SCRIPT_DOWNLOAD_SCRIPT
ECHO Please wait while script downloads...
Powershell -command "& { (New-Object Net.WebClient).DownloadFile('%server_url%%script_name%.bat', '%script_name_bat%') }"
ECHO Script Updated to v%script_latest_ver%^^!
REM User must exit script. Current batch is stale.
GOTO :END
:SCRIPT_DOWNLOAD_NOTHING
GOTO :EOF
:END
SET time_end=%time%
ECHO.
ECHO Script started:%time_start%
ECHO Script ended :%time_end%
:END_AGAIN
pause
ECHO.
ECHO Please close this window
ECHO.
GOTO END_AGAIN
You can do that through these steps:
1.put two files in server,a config file, a higher version bat file which need to update; set last version num. in config file.
2.client bat should be checked update at every startup time. you can read the news version in server config file, then compared to local bat file version. if not equal, so do update, else other wise.
Do you have any problems?
Related
I have a batch file that compiles a project and then runs a JS that connects to a DSP, runs the program and reads the results from the DSP's memory (more detailed info about the DSP etc. is at the end of my question).
My problem is that the compiling and JS running is run in a loop inside my batch file and sometimes, for some reason, the build is stuck, an exception in the DSP is thrown or the DSP is stuck in a condition that is preventing the batch to continue to the next step in the loop.
What I want to implement is some kind of a watchdog in my batch file that lets the current loop step last for a limited time and if that time expires, continue to the next step.
the DSP is TI6678EVM, using CodeComposer v5.3 and DSS.
The batch file's loop:
:CREATE_TEST_DIR
SET "test_dir=%cur_dir%%proj_name%"
ECHO %test_dir%
IF NOT EXIST %test_dir% GOTO INC_TESTN
ECHO ************************************************************************
ECHO Copying headers from %headers_folder_name%%test_num%
ECHO ************************************************************************
SET /a Idx=10
:CHANGE_HEADERS
REM Delete the header files from project dir
del %test_dir%\HeaderFiles\R_Main_%Idx%.h"
REM Copy test vectors header file to workspace
COPY /y "%test_dir%\%headers_folder_name%%test_num%\R_Main_%Idx%_%test_num%.h" "%test_dir%\HeaderFiles\R_Main_%Idx%.h"
SET /a Idx+=1
IF %Idx% leq 16 GOTO CHANGE_HEADERS
ECHO ************************************************************************
ECHO Building project
ECHO ************************************************************************
REM Create and build project
CALL "%eclipsec_path%" -noSplash -data "%test_dir%" -application com.ti.ccstudio.apps.projectBuild -ccs.workspace -ccs.buildType clean > "%test_dir%\p_build.log" || GOTO FAIL_BUILD
CALL "%eclipsec_path%" -noSplash -data "%test_dir%" -application com.ti.ccstudio.apps.projectBuild -ccs.workspace > "%test_dir%\p_build.log" || GOTO FAIL_BUILD
REM ECHO Project build successful
FOR /r "%test_dir%" %%a in (*.ccxml) do set CCXML_path=%%~dpnxa
IF "%CCXML_path%"=="" GOTO BAD_CCXML
ECHO Found .ccxml file %CCXML_path%
FOR /r "%test_dir%" %%a in (*.out) do set OUT_path=%%~dpnxa
IF "%OUT_path%"=="" GOTO BAD_OUT
ECHO Found .out file %OUT_path%
SET "testVecPath=%test_dir%\%headers_folder_name%%test_num%"
ECHO ************************************************************************
ECHO Runing tet
ECHO ************************************************************************
CALL "%dss_path%" "ccsRunTestVectors.js" %ccs_path% %test_dir% %CCXML_path% %OUT_path% %datetimef% %testVecPath%|| GOTO FAIL_BASIC
ECHO ************************************************************************
ECHO Test Done.
ECHO ************************************************************************
GOTO INC_TESTN
:FAIL_CREATE
ECHO Failed
:INC_TESTN
SET /a test_num+=1
REM pause
IF %test_num% gtr %TestNumEnd% GOTO DONE
GOTO CREATE_TEST_DIR
:DONE
Here is an example of what I mean, it will run the main loop, as long as the timer.cmd file is active with the title Timer. You can copy this as is and call it something like test_wait.cmd then run it, you will see that it will continue looping, echoing Still running as long as the script timer.cmd is running, which by the way this script creates for you.
You can then incorporate it into your script as you please.
#echo off
echo title Timer>timer.cmd
echo timeout 20 /NOBREAK ^>nul>>timer.cmd
echo exit>>timer.cmd
start /min timer.cmd & timeout 1 /NOBREAK>nul
:start
tasklist /FI "windowtitle eq Timer" | findstr /i "cmd.exe">nul 2>&1
if errorlevel 1 goto del timer.cmd /Q & goto :eof
echo Still running..
(timeout /t 1)>nul
goto :start
Been wrecking my brain all night trying to figure out why this isn't working, but one of my variables isn't releasing on the next iteration of my loop and I can't figure out why... The first pass of the loop seems to work fine, but the next iteration, the first variable gets locked and the script connects to the system that's already been configured.
I've been staring at this for a while now and no matter how I approach it, it still behaves badly. :/ The purpose is to read a text-string of a given file, and use it to modify (via Find and Replace (fnr.exe)) another file with several instances of the required data. I didn't have alot of luck with 'findstr' replacing so many instances of the text required so I went with a tool I've used before that seemed to work really well in it's previous scripting application...
Truth be told, I find myself stumbling with even the most basic code a lot of times, so any kind soul willing to impart some wisdom/assistance would be greatly appreciated!
Thanks in advance...
#ECHO ON
setlocal enabledelayedexpansion
> "%~dp0report.log" ECHO Batch Script executed on %DATE% at %TIME%
rem read computer list line by line and do
FOR /F %%A in (%~dp0workstations.txt) do (
SET lwn=
SET WKSTN=%%A
rem connect to workstation and read lwn.txt file
pushd "\\%WKSTN%\c$\"
IF ERRORLEVEL 0 (
FOR /F %%I in (\\%wkstn%\c$\support\lwn.txt) DO (
SET LWN=%%I
%~dp0fnr.exe --cl --dir "\\%WKSTN%\c$\support\folder\config" --fileMask "file.xml" --find "21XXXX" --replace "%%I"
IF ERRORLEVEL 0 ECHO Station %LWN%,Workstation %WKSTN%,Completed Successfully >> %~dp0report.log
IF ERRORLEVEL 1 ECHO Station %LWN%,Workstation %WKSTN%, A READ/WRITE ERROR OCCURRED >> %~dp0report.log
echo logwrite error 1 complete
popd
)
)
IF ERRORLEVEL 1 (
ECHO ,,SYSTEM IS OFFLINE >> %~dp0report.log
)
popd
set wkstn=
set lwn=
echo pop d complete
)
msg %username% Script run complete...
eof
The ! notation must be used on all variables that are changed inside the loop.
C:>type looptest.bat
#ECHO OFF
setlocal enabledelayedexpansion
rem read computer list line by line and do
FOR /F %%A in (%~dp0workstations.txt) do (
SET WKSTN=%%A
ECHO WKSTN is set to %WKSTN%
ECHO WKSTN is set to !WKSTN!
pushd "\\!WKSTN!\c$\"
ECHO After PUSHD, ERRORLEVEL is set to %ERRORLEVEL%
ECHO After PUSHD, ERRORLEVEL is set to !ERRORLEVEL!
IF !ERRORLEVEL! NEQ 0 (
ECHO ,,SYSTEM IS OFFLINE
) ELSE (
ECHO Host !WKSTN! is available
)
popd
)
EXIT /B 0
The workstations.txt file contained the following. (I should not give out actual host names.)
LIVEHOST1
DEADHOST1
LIVEHOST2
The output is...
C:>call looptest.bat
WKSTN is set to
WKSTN is set to LIVEHOST1
After PUSHD, ERRORLEVEL is set to 0
After PUSHD, ERRORLEVEL is set to 0
Host LIVEHOST1 is available
WKSTN is set to
WKSTN is set to DEADHOST1
The network path was not found.
After PUSHD, ERRORLEVEL is set to 0
After PUSHD, ERRORLEVEL is set to 1
,,SYSTEM IS OFFLINE
WKSTN is set to
WKSTN is set to LIVEHOST2
After PUSHD, ERRORLEVEL is set to 0
After PUSHD, ERRORLEVEL is set to 0
Host LIVEHOST2 is available
Although your code have several issues, the main one is the use of % instead of ! when you access the value of variables modified inside a for loop (although you already have the "enabledelayedexpansion" part in setlocal command). However, I noted that you sometimes use the FOR replaceable parameter (like in --replace "%%I") and sometimes you use the variable with the same value (%LWN%), so a simpler solution in your case would be to replace every %VAR% with its corresponding %%A for parameter.
I inserted this modification in your code besides a couple small changes that make the code simpler and clearer.
#ECHO ON
setlocal
> "%~dp0report.log" ECHO Batch Script executed on %DATE% at %TIME%
rem Read computer list line by line and do
FOR /F %%A in (%~dp0workstations.txt) do (
rem Connect to workstation and read lwn.txt file
pushd "\\%%A\c$\"
IF NOT ERRORLEVEL 1 (
FOR /F "usebackq" %%I in ("\\%%A\c$\support\lwn.txt") DO (
%~dp0fnr.exe --cl --dir "\\%%A\c$\support\folder\config" --fileMask "file.xml" --find "21XXXX" --replace "%%I"
IF NOT ERRORLEVEL 1 (
ECHO Station %%I,Workstation %%A,Completed Successfully >> %~dp0report.log
) ELSE (
ECHO Station %%I,Workstation %%A, A READ/WRITE ERROR OCCURRED >> %~dp0report.log
echo logwrite error 1 complete
)
)
) ELSE (
ECHO ,,SYSTEM IS OFFLINE >> %~dp0report.log
)
popd
echo pop d complete
)
msg %username% Script run complete...
Basically I have created an choice batch that every so often I can archive the contents of my boot data since I change it quite often and it works absolutely perfect, however I face the problem that every time I compile the batch from .BAT to.EXE with Advanced BAT to EXE converter the command 'bcdedit' never works and says “Not recognised as an internal or external command, operable program or batch file.”
Now the first thing I did was to make sure if I had the environment variables directed on my hard drive and it seemed fine:
Path: %SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\QuickTime\QTSystem\;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x86;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x64;C:\Users\Support\DOCUME~1\MYFILE~1\Programs\SYSTEM~1\DISKEE~1\
It has all the variables needed to work perfectly plus a few external ones which is ok then I thought that maybe I should try to make it direct on my folder, by doing some research I found on another forum:
Setting or Modifying a System Wide Environment Variable In CMD.EXE
I made a separate .BAT and I called it and it seems it did create the separate variable:
C:\Users\???\Documents\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\QuickTime\QTSystem\;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x86;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x64;C:\Users\Support\DOCUME~1\MYFILE~1\Programs\SYSTEM~1\DISKEE~1" /f
But It Still Didn't Work!
I read upon another form:
Syswow64 Redirection
The person solution was to use Create Process () to create a program that automatically redirects him to the folder using sysnative (System32) but I'm a total beginner at C#, CMD is my strongest area when it comes to coding.
Please please I beg of you to help me as soon as possible and if you do have an answer please state in the easiest way possible and why. Here's my script just in case:
:START
echo.
echo Call apath.bat
echo.
echo.
echo (E) - Start Process.
echo (C) - Launch Part 2 Of Process.
echo (N) - Load NoDrives Manager.
echo (D) - Display Currect Account and Computer Information
echo (X) - Exit EDIM.
echo.
echo NOTE - It will not work if not started with Admin Privillages.
echo.
:Choice
set/p Option=Please enter your option:
if '%Option%' == 'E' goto :Incognito
if '%Option%' == 'C' goto :Touch
if '%Option%' == 'N' goto :Manager
if '%Option%' == 'D' goto :Data
if '%Option%' == 'X' goto :Exit
echo.
echo.
echo Invalid Option - Please Reselect.
goto :Choice
:RetryE
Echo An Error was found!
set/p RetryE=Retry? Y/N:
if '%RetryE%' == 'Y' goto :Incognito
if '%RetryE%' == 'N' goto :Exit
:Incognito
Timeout 5
echo.
echo.
echo.
Echo Saving OriginalBCD...
bcdedit /export "Data/BCD/OriginalBCD"
IF %ERRORLEVEL% GTR 0 goto :RetryE
IF %ERRORLEVEL% LSS 0 goto :RetryE
Echo Checking presence of BCD...
IF NOT EXIST "Data/BCD/OriginalBCD" goto :RetryE
Echo Deleting Boot Entry...
bcdedit /delete {current}
IF %ERRORLEVEL% GTR 0 goto :RetryE
IF %ERRORLEVEL% LSS 0 goto :RetryE
Echo Saving EditedBCD...
bcdedit /export "Data/BCD/IncogBCD"
IF %ERRORLEVEL% GTR 0 goto :RetryE
IF %ERRORLEVEL% LSS 0 goto :RetryE
Echo Checking presence of BCD...
IF NOT EXIST "Data/BCD/IncogBCD" goto :RetryE
Echo Allowing User Control For Assigning System Reserved Partitions...
Echo -Commands-
Echo Diskpart
Echo List volume
Echo Select Volume "" (The one that has no Letter and remember number)
Echo Assign Letter=Z
Echo Select Volume "" (The one that has Letter E and remember number)
Echo Remove Letter=E (This is the new system reserved partition)
Echo Then exit Diskpart to finish Part 1.
Diskpart
Echo Ready To Restart!
Timeout 5
Shutdown /r /t 30
Goto :Start
:RetryC
set/p RetryE=Retry? Y/N:
if '%RetryC%' == 'Y' goto :Touch
if '%RetryC%' == 'N' goto :Exit
:Touch
echo.
echo.
echo.
Echo Loading NDM...
Echo NOTE - Store the password somewhere safe!!!
Start "" "Data/NDM.exe"
Echo Loading EditedBCD...
bcdedit /import "Data/BCD/IncogBCD"
IF %ERRORLEVEL% GTR 0 goto :RetryC
IF %ERRORLEVEL% LSS 0 goto :RetryC
Echo Process Complete!
Timeout 5
Echo Returning to menu...
goto :Start
:Manager
echo.
Echo NOTE - Store the password somewhere safe!!!
Start "" /WAIT "Data/ndm.exe"
Echo Returning to Menu...
goto :Start
:Data
echo.
echo.
echo.
echo Processing Data...
Systeminfo
diskpart /s "Data/discpart.txt"
Echo Returning to Menu...
goto :Start
:Exit
Exit
Thanks So Much!
bcdedit is on the path by default so unless you are reusing the PATH variable then the problem is in the batch compiler.
You can test this by using the plain batch file - and if it works then you know where the problem is.
I am writing a batch script that will loop through each line of a text file, (each line containing a filename) check if the file exists and then runs the file and moves it.
Here is my batch script:
REM Loop through each line of input.txt
FOR /F "tokens=1-3 delims=, " %%i IN (./ready/input.txt) DO (
ECHO.
ECHO.
ECHO.
ECHO Check %%i exists, set error flag if it doesnt
if not exist .\ready\%%i set errorlevel=2
echo return code is %errorlevel%
ECHO Run %%i if it exists
if errorlevel 0 call .\ready\%%i
ECHO Move %%i to archive if no error occured
if errorlevel 0 copy .\ready\%%i .\archive\%mydate%_%mytime%_%%j_%%k_%%i
ECHO Copy line of text to the new output.txt file if an error occured
if %errorlevel% NEQ 0 >>output.txt %%i, %%j, %%k
)
Here is the output:
I do not understand why the "if errorlevel" is not working as expected... if the file does not exist (as in this example where it does not exist) it should NOT try to run the file, it should NOT copy the file, and it should echo a 2 not a 0
Edit 1: I was reading another SO Post regarding "delayed environment variable expansion" I am not sure if this issue is related
ERRORLEVEL and %ERRORLEVEL% are two different variables. That means your code with echo return code is %errorlevel% and if %errorlevel% NEQ 0 >>output.txt %%i, %%j, %%k is probably wrong.
ERRORLEVEL is builtin and used to fetch the result of the last command. You can use it like:
IF ERRORLEVEL 1 ECHO error level is 1 or more
ERRORLEVEL cannot be set, just like bash does not let you set ?= ...
%ERRORLEVEL% is an environmental variable. If %ERRORLEVEL% is set, then its used in your script when you use %ERRORLEVEL%. If %ERRORLEVEL% is not set AND if command extensions are enabled, then it falls back to ERRORLEVEL. ERRORLEVEL does not update %ERRORLEVEL%.
Raymond Chen has a good blog entry on it: ERRORLEVEL is not %ERRORLEVEL%. Some of the content in this answer was shamelessly lifted from it.
#ECHO OFF
SETLOCAL
DEL output.txt 2>nul
REM Loop through each line of input.txt
FOR /F "tokens=1-3 delims=, " %%i IN (.\ready\input.txt) DO (
ECHO.
ECHO.
ECHO.
ECHO Check %%i exists, set error flag if it doesnt
if exist .\ready\%%i (set "errorflag=") ELSE (set errorflag=2)
CALL echo return code is %%errorflag%%
ECHO Run %%i if it exists
if NOT DEFINED errorflag (
call .\ready\%%i
ECHO Move %%i to archive if no error occured
if errorlevel 1 (SET errorflag=3) ELSE (ECHO copy .\ready\%%i .\archive\%mydate%_%mytime%_%%j_%%k_%%i)
)
ECHO Copy line of text to the new output.txt file if an error occured
if DEFINED errorflag >>output.txt ECHO %%i, %%j, %%k
)
GOTO :EOF
Here's a rewritten procedure.
Note: output.txt is deleted at the start, else the >> would append to any existing file. 2>nul suppresses error messages if the delete fails (eg. file not exist)
Within a block statement (a parenthesised series of statements), the ENTIRE block is parsed and THEN executed. Any %var% within the block will be replaced by that variable's value AT THE TIME THE BLOCK IS PARSED - before the block is executed.
Hence, IF (something) else (somethingelse) will be executed using the values of %variables% at the time the IF is encountered.
Two common ways to overcome this are 1) to use setlocal enabledelayedexpansion and use !var! in place of %var% to access the chnaged value of var or 2) to call a subroutine to perform further processing using the changed values.
Note therefore the use of CALL ECHO %%var%% which displays the changed value of var. CALL ECHO %%errorlevel%% displays, but sadly then RESETS errorlevel.
IF DEFINED var is true if var is CURRENTLY defined.
ERRORLEVEL is a special varable name. It is set by the system, but if set by the user, the user-assigned value overrides the system value.
IF ERRORLEVEL n is TRUE if errorlevel is n OR GREATER THAN n. IF ERRORLEVEL 0 is therefore always true.
The syntax SET "var=value" (where value may be empty) is used to ensure that any stray spaces at the end of a line are NOT included in the value assigned.
The required commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO COPY to COPY to actually copy the files.
I used the following input.txt:
seterr1.bat, J1, K1
seterr5.bat,J2,K2
seterr0.bat,J3 K3
seterr5.bat, J4, K4
notexist.bat, J5, K5
With existing files seterr*.bat which contain
#ECHO OFF
EXIT /b 1
(where the 1 in the last line determines the errorlevel returned)
and received the resultant output:
Check seterr1.bat exists, set error flag if it doesnt
return code is
Run seterr1.bat if it exists
Move seterr1.bat to archive if no error occured
Copy line of text to the new output.txt file if an error occured
Check seterr5.bat exists, set error flag if it doesnt
return code is
Run seterr5.bat if it exists
Move seterr5.bat to archive if no error occured
Copy line of text to the new output.txt file if an error occured
Check seterr0.bat exists, set error flag if it doesnt
return code is
Run seterr0.bat if it exists
Move seterr0.bat to archive if no error occured
copy .\ready\seterr0.bat .\archive\__J3_K3_seterr0.bat
Copy line of text to the new output.txt file if an error occured
Check seterr5.bat exists, set error flag if it doesnt
return code is
Run seterr5.bat if it exists
Move seterr5.bat to archive if no error occured
Copy line of text to the new output.txt file if an error occured
Check notexist.bat exists, set error flag if it doesnt
return code is 2
Run notexist.bat if it exists
Copy line of text to the new output.txt file if an error occured
Note that the COPY is merely ECHOed as I mentioned earlier.
and output.txt
seterr1.bat, J1, K1
seterr5.bat, J2, K2
seterr5.bat, J4, K4
notexist.bat, J5, K5
Use something like the following subroutine:
:return
ECHO #exit /b %1 >ret.cmd
CALL ret.cmd
GOTO :eof
Then use it like this:
:Attempt
SETLOCAL
CALL somethingThatFails
SET retcode=!errorlevel!
CALL somethingThatPasses : don't care about the errorlevel here
CALL :return !retcode!
ENDLOCAL
CALL :eof
So, the whole thing would looke something like:
test.cmd...
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
CALL :Attempt
IF !errorlevel! NEQ 0 (ECHO Attempt Failed) ELSE (ECHO Attempt succeeded!)
GOTO :eof
:Attempt
SETLOCAL
CALL somethingThatFails
SET retcode=!errorlevel!
CALL somethingThatPasses : don't care about the errorlevel here
CALL :return %retcode%
ENDLOCAL
CALL :eof
:return
ECHO #exit /b %1 >return.cmd
CALL ret.bat
GOTO :eof
somethingthatfails.cmd...
DIR some command that fails >nul 2>&1
somethingthatpasses.cmd...
DIR >nul 2>&1
The one side effect of this is a file laying around called ret.cmd. I usually use an :end subroutine that does cleanup and would delete it.
There is an easy way to set the %errorlevel% with a trick I learned several years ago:
:: force errorlevel to 1
#(call)
echo %errorlevel%
:: force errorlevel to 0
#(call )
echo %errorlevel%
pause
The space after call is necessary to set the %errorlevel% to 0.
Update: After researching this, I found a reference here.
For posterity, when specifically setting it to 0, I like
ver >nul
ver.exe always returns 0.
This is designed to execute the %%i item only if it exists and follow through with checking for errors and move or log. if the %%i item doesn't exist then it will do nothing.
REM Loop through each line of input.txt
FOR /F "tokens=1-3 delims=, " %%i IN (.\ready\input.txt) DO (
ECHO.
ECHO.
ECHO.
ECHO Check %%i exists, execute it if it does
if exist .\ready\%%i (
call .\ready\%%i
ECHO Move %%i to archive if no error occured
if not errorlevel 1 (
copy .\ready\%%i .\archive\%mydate%_%mytime%_%%j_%%k_%%i
) else (
ECHO Copy line of text to the new output.txt file if an error occurred
>>output.txt %%i, %%j, %%k
)
)
)
for me, simple use of cmd /c exit 2 worked to set the errorlevel and use it locally in a batch file and even after it ended to ask for the errorlevel outside:
set errorlevel=2
:
cmd /c exit %errorlevel%
:
if errorlevel 3 echo 3
if errorlevel 2 echo 2
if errorlevel 1 echo 1
if errorlevel 1 echo 0
Results
>test.bat
2
1
0
>if errorlevel 2 echo 2
2
#echo off
color 4
ping localhost 2.5 > nul
echo Welcome to the configuration menu.
echo Move AH1.exe and AH2.exe to your desktop.
echo This only works the first time
echo SO BE CAREFUL!
echo Would you like this to start on computer startup?
echo say "yes" or "no" below.
set /p option=Option:
IF %ERRORLEVEL% EQU no goto no
IF %ERRORLEVEL% EQU yes goto yes
:yes
echo Move AH1.bat and AH2.bat to desktop.
::Copies files to dekstop of current user *For Windows 7
xcopy "%systemdrive%\users\%username%\Desktop\AH1.bat" "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup"
xcopy "%systemdrive%\users\%username%\Desktop\AH2.bat" "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup"
echo Moved.
echo Press any key to close Anti Hacker Configuration.
pause > nul
exit
:no
echo No?The program will not take full effect then.
pause
exit
If you want to test,make 2 batch files on your desktop called AH1 and AH2
It says Access Denied....why??
No matter what you put into the option variable, it will always go to :yes.
I'm guessing you got mixed up with the choice command when you were making this because errorlevel doesn't contain the option you choose when you have the set command.
From the set documentation:
%ERRORLEVEL% - expands to the current ERRORLEVEL value
So, you might want to change if %errorlevel% equ no goto no to if %option% equ no goto no.
Also, what happens if you don't put either yes nor no. You need to account for these things by perhaps having a exit command after the second if statement.