Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to get a windows batch file to update itself safely

Tags:

batch-file

e.g. I want to run a windows batch file, say upgrade.bat, which copies a bunch of files from a source directory to the directory that the batch file is in. Problem is, one of the files copied might be a newer version of upgrade.bat, so that the batch file will overwrite itself while its still running.

This seems to result in some unpredictable behavior of batch file execution, so I want to avoid copying over a batch file which is still running. Ideally, I want the existing version of upgrade.bat to run until it is finished, and next time run the new version. Are there any (simple) ways to achieve this ?

like image 785
Moe Sisko Avatar asked Jun 19 '13 00:06

Moe Sisko


4 Answers

@ECHO OFF
SETLOCAL
IF /i NOT "%~dp0"=="%temp%\" (
 COPY /y "%~dpnx0" "%temp%\%~nx0" >nul
 "%temp%\%~nx0"

)
ECHO Now we run the rest of the original UPGRADE.BAT

This sequence of lines at the start of upgrade.bat should work.

See whether we're running from a copy in %temp%. If not, then copy this file to temp & run it from there.

Hence the batch actually runs from %temp% and the original version may be overwritten.

like image 23
Magoo Avatar answered Oct 09 '22 18:10

Magoo


if NOT "%1"=="RUN" (
copy "%~0" temp_update.cmd
temp_update.cmd RUN
)

Just put this at the top of your cmd file any name can be used for the temporary file.

like image 109
SteveSi Avatar answered Sep 28 '22 02:09

SteveSi


In order to do that, the following requirements must be satisfied:

  • The overwrite of the Batch file for the newer version of itself must be the last command of the Batch file, so the next command after the copy must be an exit /B or exit.
  • Previous commands must be loaded in memory before they are executed. This is easily done by enclosing them in parentheses.

That is:

@echo off
rem Do program business here...
echo Anything

rem Parse/load following commands before execute they:
(
rem Copy many files, probably a newer version of myself
xcopy /Y *.*
rem You may execute other commands here...
echo Files copied!
rem Terminate *this version* of the running Batch file
exit /B
)
like image 6
Aacini Avatar answered Oct 09 '22 19:10

Aacini


You can run the copy as the last operation using the start command to launch it from another terminal. Check this example, specially the last lines.

@echo off
set CUR_FILE=batman.bat
set FOUND_EQUAL="FALSE"
set FROM_DIR=c:\temp\galeria\

SETLOCAL DisableDelayedExpansion
FOR /R %FROM_DIR% %%F IN (*) DO (
  SET "p=%%F"
  SETLOCAL EnableDelayedExpansion
  SET ABC=!p:%FROM_DIR%=!

  IF NOT !ABC! == !CUR_FILE! ( 
echo copying %%F
    copy "%%F" . 
   )    
ENDLOCAL  
) 

echo trying to copy file with the same name [last operation] 
start copy "%FROM_DIR%%CUR_FILE%" .
like image 4
br araujo Avatar answered Oct 09 '22 18:10

br araujo