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
Related
I am facing a problem with my following batch script, where I can see how the execution of the command %nr% --f !path2! never seems to happen and I don't understand the reason.
What am I doing wrong? Too many nested conditions ?
EDIT: adding WRONG code where comments are enabled
rem The call to this batch script will be this
rem C:/Projects/DevelopmentTools/SDKs/TP/B/Scrpt/Exg_Serial_Flasher.bat EF.hex DH.hex C:/Projects/DevelopmentTools/SDKs/TP/B/E/Output/CN/Exe/
setlocal enabledelayedexpansion
set nr=nr.exe
if "%1"=="" (
if "%2"=="" (
if "%3"=="" (
echo "[Error]"
set "runScript="
)
)
) else (
set "input1=%1"
set "input2=%2"
set "path3=%3%nr%"
set "myPath"=%3"
set "path1=!myPath!!input1!"
set "path2=!myPath!!input2!"
rem Control variable
set "runScript=true"
)
if defined runScript (
if exist "%path3%" (
%nr% --check
if exist !path1! (
%nr% --f !input1!
echo !ERRORLEVEL!
if !ERRORLEVEL! EQU 0 (
echo !input1! set correctly
if exist !path2! (
echo Setting !exgSerial!
%nr% --f !input2!
if !ERRORLEVEL! EQU 0 (
echo Everything went fine
)
)
)
)
)
)
Thanks!
I suggest following batch code:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "ExeFile=nr.exe"
if "%~1" == "" goto ArgumentError
if "%~2" == "" goto ArgumentError
if not "%~3" == "" goto ProcessArguments
:ArgumentError
echo Error: %~nx0 must be called with three arguments.
exit /B 1
:ProcessArguments
rem Assign third argument to an environment variable.
set "FilePath=%~3"
rem Replace forward slashes by backslashes which is the directory separator on Windows.
set "FilePath=%FilePath:/=\%"
rem Make sure the file path ends with a backslash.
if not "%FilePath:~-1%" == "\" set "FilePath=%FilePath%\"
set "HexFile1=%FilePath%%~1"
set "HexFile2=%FilePath%%~2"
set "ExeFile=%FilePath%%ExeFile%"
if not exist "%ExeFile%" echo Error: "%ExeFile%" does not exist. & exit /B 2
if not exist "%HexFile1%" echo Error: "%HexFile1%" does not exist. & exit /B 3
if not exist "%HexFile2%" echo Error: "%HexFile2%" does not exist. & exit /B 3
"%ExeFile%" --check
"%ExeFile%" --f "%HexFile1%"
if errorlevel 1 echo Error: Processing "%HexFile1%" failed. & exit /B 4
"%ExeFile%" --f "%HexFile2%"
if errorlevel 1 echo Error: Processing "%HexFile2%" failed. & exit /B 4
echo Everything worked fine.
endlocal
An error condition is detected as soon as possible with resulting in exiting batch file processing with an appropriate error message and exit code.
There is no need for delayed environment variable expansion which makes processing the batch file faster and avoids problems with directory or file names containing an exclamation mark.
Name of a file or the file path can contain also command line critical characters like space or one of these characters &()[]{}^=;!'+,`~.
There are no nested IF conditions making successful execution flow straight from top to bottom.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /? ... explains %~1 which expands to argument 1 with removing any surrounding quotes.
echo /?
endlocal /? ... used here implicit on exiting batch file processing with exit and explicit at end of batch file.
exit /?
goto /?
if /?
rem /?
setlocal /?
See also Single line with multiple commands using Windows batch file.
I think I found the issue, it has to do with the fact that the "echos" to debug seem to influence the script execution. So in the code of my question, if I enable the echos, the script will fail running whereas if I disable them( commented out as below), the script does work.
Nevertheless, I don't understand why it does fail with the echos in first instance.
Code with disabled echos and working
rem The call to this batch script will be this
rem C:/Projects/DevelopmentTools/SDKs/TP/B/Scrpt/Exg_Serial_Flasher.bat EF.hex DH.hex C:/Projects/DevelopmentTools/SDKs/TP/B/E/Output/CN/Exe/
setlocal enabledelayedexpansion
set nr=nr.exe
if "%1"=="" (
if "%2"=="" (
if "%3"=="" (
echo "[Error]"
set "runScript="
)
)
) else (
set "input1=%1"
set "input2=%2"
set "path3=%3%nr%"
set "myPath"=%3"
set "path1=!myPath!!input1!"
set "path2=!myPath!!input2!"
rem Control variable
set "runScript=true"
)
if defined runScript (
if exist "%path3%" (
%nr% --check
if exist !path1! (
%nr% --f !input1!
rem echo !ERRORLEVEL!
if !ERRORLEVEL! EQU 0 (
rem echo !input1! set correctly
if exist !path2! (
rem echo Setting !exgSerial!
%nr% --f !input2!
if !ERRORLEVEL! EQU 0 (
echo Everything went fine
)
)
)
)
)
)
I'm facing an issue when trying to implement the ERRORLEVEL on my batch script. Basically what I'm trying to do is: look for the .txt files in the directory and if found; .txt will get listed, if not found; message error will occur.
The thing is that this directory will not always contain a .txt, sometimes it will be empty and when that happens my code will not work. Only when there is a .txt in the directory I'm getting my conditions to work (ERRORLEVEL = 0), but if empty; none of my conditions will. Not even the ERRORLEVEL will be printed in the cmd screen (I should see it as ERRORLEVEL = 1).
This is my code:
for /r "C:\Texts" %%a in (*.txt) do (
echo %errorlevel%
IF ERRORLEVEL 0 (
echo %%a
echo "I found your Text!"
) ELSE (
echo "I couldn`t find your Text!" )
)
What exactly is wrong with my ERRORLEVEL implementation?
Errorlevel 0 is always true.
Use
if not errorlevel 1
But your code doesn't set the errorlevel.
In your code there is not any command that set the errorlevel. This value is set by all external .exe commands (like find or findstr), and by certain specific internal commands (like verify that set errorlevel=1 when its parameter is wrong, or ver that always set the errorlevel=0.
You may explicitly set this value in your code this way:
rem Set the errorlevel to 1
verify bad 2> NUL
for /r "C:\Texts" %%a in (*.txt) do (
echo %%a
rem Set the errorlevel to 0
ver > NUL
)
if not ERRORLEVEL 1 (
echo "I found your Text!"
) else (
echo "I couldn't find your Text!"
)
However, you may also get a similar result using a Batch variable instead of the errorlevel...
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...
Scenario: I have a pre-commit batch script that checks for blank comments, and calls a vbscript file for authorization of the user.
The vbscript file then exits by wscript.echo 1 or wscript.echo 0 after which the control comes back to the batch file to exit with success or failure.
#ECHO OFF
set REPOS=%1
set TXN_NAME=%2
set DEBUG=0
SET ThisScriptsDirectory=%~dp0
set svnlook = "C:\Program Files\TortoiseSVN\bin\"
REM: check for blank comment
for /f "tokens=*" %%a in ('%svnlook% svnlook author -t %TXN_NAME% %REPOS%') do set AUTH_NAME=%%a
%svnlook% svnlook log %REPOS% -t %TXN_NAME% | findstr .................... > nul
if %errorlevel% gtr 0 (goto err) else (goto noerr)
:err
echo. 1>&2
echo Your commit has been blocked because you didn't enter a comment. 1>&2
echo Write a log message describing the changes made and try again. 1>&2
echo Thanks 1>&2
exit 1
:noerr
for /f %%i in ('cscript.exe //nologo %ThisScriptsDirectory%pre-commiting.vbs %REPOS% %TXN_NAME% %ThisScriptsDirectory% %AUTH_NAME%') do set vars = %%i
if %vars% == "0" ( goto success) else (goto failure)
:failure
echo. 1>&2
echo You do not have the permissions to work on this repository. 1>&2
echo Request modifications access from support team. 1>&2
echo Thanks 1>&2
exit 1
:success
echo Commit Authorized...
exit 0
I tried doing an echo of my vbscript to a file and it seems to return 1 or 0 which is what I am expecting it to do..
Thanks in advance. . .
The spaces in the set command are important, and included both in the value and in the name of the variable.
....
.... set "vars=%%i"
if operators will only work if the left and the right operands follow the same rules. If you quote one value, quote also the other. If not, one value will have quotes, the other not and condition will always evalueate to false
if "%vars%"=="0"
if %vars%==0
if "%vars%" equ "0"
if %vars% equ 0
Spaces are significant in SET assignments.
You have set vars = %%i, which defines a variable named "vars[space]", with a value of "[space]0" or "[space]1". Simply remove the spaces before and after the equal sign.
set vars=%%i
I used both the solutions given here..
I modified my loop where the set statement is used.
do set "vars=%%i"
I modified my comparison operator by adding quotes on both the sides
if "%vars%"=="0" ( goto success) else (goto failure)
and the code ran like a knife on butter :)
+1 to both for a nice explanation..
Thanks,
Venkat.
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?