Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/tfs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Batch file 如何让windows批处理文件安全地自我更新_Batch File - Fatal编程技术网

Batch file 如何让windows批处理文件安全地自我更新

Batch file 如何让windows批处理文件安全地自我更新,batch-file,Batch File,e、 我想运行一个windows批处理文件,比如upgrade.bat,它将一组文件从源目录复制到批处理文件所在的目录。问题是,复制的其中一个文件可能是更新版本的upgrade.bat,因此批处理文件将在其仍在运行时覆盖自身 这似乎会导致批处理文件执行的某些不可预测的行为,因此我希望避免复制仍在运行的批处理文件。理想情况下,我希望upgrade.bat的现有版本一直运行到完成,下次再运行新版本。有什么(简单的)方法可以实现这一点吗?是否可以选择在批处理文件的每个新版本上标记一个版本后缀,并使用第

e、 我想运行一个windows批处理文件,比如upgrade.bat,它将一组文件从源目录复制到批处理文件所在的目录。问题是,复制的其中一个文件可能是更新版本的upgrade.bat,因此批处理文件将在其仍在运行时覆盖自身


这似乎会导致批处理文件执行的某些不可预测的行为,因此我希望避免复制仍在运行的批处理文件。理想情况下,我希望upgrade.bat的现有版本一直运行到完成,下次再运行新版本。有什么(简单的)方法可以实现这一点吗?

是否可以选择在批处理文件的每个新版本上标记一个版本后缀,并使用第二个批处理文件作为启动程序


例如,假设您的有效负载批处理文件为升级.bat,后续版本将命名为升级\u 001.bat、升级\u 002.bat、升级\u 003.bat。。或者升级_201305122134(后缀为yyyymmddHHMM),新的批处理文件launcher.bat将通过查找后缀最高的批处理升级文件来查找最新的批处理升级文件并执行它

您可以使用start命令将副本作为最后一个操作运行,从另一个终端启动它。检查这个例子,特别是最后几行

@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%" .

为此,必须满足以下要求:

  • 更新版本的批处理文件自身的覆盖必须是批处理文件的最后一个命令,因此
    copy
    之后的下一个命令必须是
    exit/B
    exit
  • 在执行以前的命令之前,必须将其加载到内存中。将它们括在括号中很容易做到这一点
即:

@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
)
这将启动一个新的cmd进程,并将当前批处理文件替换为“C:\somepath\upgrade.bat”,然后重新启动批处理文件

@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
升级.bat开始时的这一行序列应该可以工作

查看是否从
%temp%
中的副本运行。如果没有,则将此文件复制到temp并从那里运行它


因此,批处理实际上从
%temp%
运行,原始版本可能会被覆盖。

将批处理文件自身复制到
updateNow.bat
,然后运行
updateNow.bat
: 因此,
update.bat
的内容是:

if %0 == update (
  copy update.bat updateNow.bat
  updateNow.bat
) else (
  copy newUpdate.bat update.bat
)
只要把它放在你的cmd文件的顶部
临时文件可以使用任何名称。

在执行之前重命名该文件?@Chad-您的意思是从upgrade.bat内部重命名upgrade.bat吗?这是安全的,并且会导致可预测的行为吗?这不是一个坏主意,我认为您已经了解了启动程序批处理文件的想法。虽然upgrade.bat在源代码管理中,所以每次更改时都不想重新命名它。@Peter_Wright:这看起来很有趣,但为什么“ECHO Now we run the rest of the original upgrade.bat”。。。复制文件后运行并运行?@steve运行原始文件时,目录不是临时目录,因此将副本复制到临时目录并执行,从而将执行转移到副本。当副本运行时,%0在临时目录中,因此它从副本中运行原始代码(即,从ECHO开始)。现在-如果您的原始代码在
%temp%
中,您可能会遇到错误,因为您试图将一个文件复制到其自身上。@Peter_Wright:一旦我发现了那个奇怪的语法,它就非常简单和优雅了。我对它进行了轻微的修改,在运行它并退出之后也将其从temp中删除。
if %0 == update (
  copy update.bat updateNow.bat
  updateNow.bat
) else (
  copy newUpdate.bat update.bat
)
if NOT "%1"=="RUN" (
copy "%~0" temp_update.cmd
temp_update.cmd RUN
)