使用 robocopy 的构建后事件突然停止工作



我在使用 robocopy 的构建后事件时遇到问题。该代码几天前曾经工作过,现在它在我的任何项目中都不起作用。下面是我用于构建后事件的代码,用于为同一应用程序的不同版本创建插件。

根据Squashman和Mofi的建议进行编辑:

echo Configuration: $(Configuration)

set "Dir2018=C:Program FilesRuneAltem 2018Plugins"
set "Dir2019=C:Program FilesRuneAltem 2019Plugins"
set "Dir2020=C:Program FilesRuneAltem 2020Plugins"

if $(Configuration) == Debug2018 goto 2018
if $(Configuration) == Debug2019 goto 2019
if $(Configuration) == Debug2020 goto 2020

:2018

echo Copying results to 2018
if not exist "%Dir2018%$(ProjectName)" mkdir "%Dir2018%$(ProjectName)"
robocopy $(TargetDir) "%Dir2018%$(ProjectName)" /XF "*.pdb" /E
if %errorlevel% leq 1 exit 0 else exit %errorlevel%

goto exit

:2019

echo Copying results to 2019
if not exist "%Dir2019%$(ProjectName)" mkdir "%Dir2019%$(ProjectName)"
robocopy "$(TargetDir)" "%Dir2019%$(ProjectName)" /XF "*.pdb" /E
if %errorlevel% leq 1 exit 0 else exit %errorlevel%

goto exit

:2020

echo Copying results to 2020
if not exist "%Dir2020%$(ProjectName)" mkdir "%Dir2020%$(ProjectName)"
robocopy $(TargetDir) "%Dir2020%$(ProjectName)" /XF "*.pdb" /E
if %errorlevel% leq 1 exit 0 else exit %errorlevel%

goto exit

:exit

错误显示在可视化工作室中:

Severity    Code    Description Project File    Line    Suppression State
Error       The command "echo Configuration: Debug2019

set "Dir2018=C:Program FilesRuneAltem 2018Plugins"
set "Dir2019=C:Program FilesRuneAltem 2019Plugins"
set "Dir2020=C:Program FilesRuneAltem 2020Plugins"

if Debug2019 == Debug2018 goto 2018
if Debug2019 == Debug2019 goto 2019
if Debug2019 == Debug2020 goto 2020

:2018

echo Copying results to 2018
if not exist "%Dir2018%SnoopTool" mkdir "%Dir2018%SnoopTool"
robocopy C:UsersusernameOneDrive_WORK FILES_REPOSnw_issuecreatornw_issuecreatorSnoopToolbinDebug2019 "%Dir2018%SnoopTool" /XF "*.pdb" /E
if %errorlevel% leq 1 exit 0 else exit %errorlevel%

goto exit

:2019

echo Copying results to 2019
if not exist "%Dir2019%SnoopTool" mkdir "%Dir2019%SnoopTool"
robocopy "C:UsersusernameOneDrive_WORK FILES_REPOSnw_issuecreatornw_issuecreatorSnoopToolbinDebug2019" "%Dir2019%SnoopTool" /XF "*.pdb" /E
if %errorlevel% leq 1 exit 0 else exit %errorlevel%

goto exit

:2020

echo Copying results to 2020
if not exist "%Dir2020%SnoopTool" mkdir "%Dir2020%SnoopTool"
robocopy C:UsersusernameOneDrive_WORK FILES_REPOSnw_issuecreatornw_issuecreatorSnoopToolbinDebug2019 "%Dir2020%SnoopTool" /XF "*.pdb" /E
if %errorlevel% leq 1 exit 0 else exit %errorlevel%

goto exit

:exit" exited with code 16. SnoopTool
Invalid Parameter #3 : "C:Program FilesRuneAltem 2019PluginsSnoopTool" 

if not exist %Dir2019%$(ProjectName) mkdir %Dir2019%$(ProjectName)成功执行。 如果目录不存在,它将创建目录。但是,我认为问题出在下一行robocopy $(TargetDir) %Dir2019%$(ProjectName) /XF "*.pdb" /E.我没有在应用程序中更改任何内容,这在我的所有项目中都发生了。这可能是关于机器人副本如何工作的更新吗?我不确定。这里完全不解。

编辑:

我更新了我的代码以遵循Squashman和Mofi的建议,但错误仍然存在。我继续删除大部分事件后代码以缩小错误范围:

echo Configuration: $(Configuration)

echo Copying results to 2019
robocopy $(TargetDir) "C:UsersusernameDocumentsNew folder (2)"
if %errorlevel% leq 1 exit 0 else exit %errorlevel%
:exit

即使有明确的路径,错误仍然会弹出:

Invalid Parameter #3 : "C:UsersoscarramirezDocumentsNew folder (2)"

感谢您的任何帮助。如果不是很明显,在代码方面,我是一个业余爱好者。我绝不是开发人员,所以如果我的错误是一个巨大的新手错误,请保持温和。

我建议为批处理文件编写以下代码:

echo Configuration: $(Configuration)
set "ConfigNumber=$(Configuration)"
set "ConfigNumber=%ConfigNumber:~-4%"
echo Copying results to %ConfigNumber%
%SystemRoot%System32robocopy.exe "$(TargetDir)" "C:Program FilesRuneAltem %ConfigNumber%Plugins$(ProjectName)" /XF "*.pdb" /E /R:3 /W:5

就是这样。

另一个工作代码是:

echo Configuration: $(Configuration)
set "ConfigNumber=$(Configuration)"
set "ConfigNumber=%ConfigNumber:~-4%"
echo Copying results to %ConfigNumber%
set "SourceDirectory=$(TargetDir)"
if "%SourceDirectory:~-1%" == "" set "SourceDirectory=%SourceDirectory%"
%SystemRoot%System32robocopy.exe "%SourceDirectory%" "C:Program FilesRuneAltem %ConfigNumber%Plugins$(ProjectName)" /XF "*.pdb" /E /R:3 /W:5

第二个代码也适用于$(TargetDir)被不以反斜杠结尾的目录路径替换。

Configuration引用$(Configuration)的 Visual Studio 变量的字符串值将由 Visual Studio 替换,例如,在第一个和第二个命令行中替换为Debug2019。因此,第二行使用字符串Debug2019定义环境变量ConfigNumber

第三行仅使用当前字符串值的最后四个字符重新定义环境变量ConfigNumber。因此,ConfigNumber是用第三行之后2019字符串定义的。

对于最后一个命令行,除了在命令提示符窗口中运行robocopy /?的使用帮助输出之外,有关ROBOCOPY的两个事实以及 robocopy 的Microsoft文档以及有关 ROBOCOPY 和 ROBOCOPY 退出代码.exe SS64 文章:

  1. ROBOCOPY将反斜杠留给一个",分别解释为"的转义字符。在所有其他情况下,反斜杠被解释为文字字符。
  2. 整个目标目录树由ROBOCOPY在尚不存在的目录树上自动创建。

Visual Studio将$(TargetDir)替换为分配给Visual Studio变量的字符串值TargetDir该值以反斜杠结尾。

Windows 命令处理器cmd.exe必须在ROBOCOPY命令行中使用,"$(TargetDir)"也可用于包含空格或这些字符之一的目录路径&(){}^=;!'+,`~

由于第一个事实,ROBOCOPY将目录路径末尾的反斜杠解释为"的转义字符。因此,ROBOCOPY会将目标路径末尾的"解释为属于目标路径的文字字符,尽管目录路径根本不能包含字符",如Microsoft有关命名文件、路径和命名空间的文档中所述。因此,ROBOCOPY会将目标参数字符串开头的所有"内容解释为源参数字符串。这显然是ROBOCOPY不想要的参数字符串解释。

该解决方案追加到$(TargetDir)一个额外的反斜杠并用于源参数"$(TargetDir)"。Visual Studio 生成的目标目录路径末尾的反斜杠现在被解释为ROBOCOPY显式添加到参数字符串的反斜杠的转义字符。第一个目录路径参数字符串末尾的双引号字符现在由ROBOCOPY解释为源目录路径的末尾。

也可以使用带有表示当前目录的点的"$(TargetDir)."在这种情况下,ROBOCOPY将反斜杠解释为文字字符,因为下一个字符是.而不是"。Windows 文件管理会将现在以.结尾的目录路径替换为绝对目录路径,而不是以ROBOCOPY上访问源目录.结尾的绝对目录路径。

无需使用命令IF检查文件复制任务的目标目录是否存在,也无需在不存在时使用命令MKDIR创建目标目录。ROBOCOPY在尚不存在的目标目录上自动将整个目录树创建到指定的目标目录。

Windows命令处理器将ROBOCOPY的退出代码分别传递给调用批处理文件调用进程。所以不需要更多的生产线。

也可以在第二个代码中使用:

if "%SourceDirectory:~-1%" == "" set "SourceDirectory=%SourceDirectory:~0,-1%"

该命令行删除目录路径末尾的反斜杠,而不是再附加一个反斜杠。这适用于所有目录路径,但驱动器根目录的路径除外,即C:E:.Visual Studio 构建的目标目录不太可能是驱动器的根目录,但仍然是可能的。

ROBOCOPY以 0 到 7 范围内的值退出,复制文件时未发生错误。如果复制时出错,则ROBOCOPY退出代码为 8 或更大。

作为生成后步骤执行的批处理文件中的最后一行也可能是以下两行之一:

if not errorlevel 8 (exit /B 0) else exit /B 1
if not errorlevel 2 exit /B 0

第一个命令行退出批处理文件处理,退出代码0ROBOCOPY退出,值范围为07,否则退出代码1

第二个命令行退出批处理文件处理,退出代码0ROBOCOPY上的退出值为01,否则退出代码为ROBOCOPY的退出代码,命令IF未修改。

请在命令提示符窗口中运行if /?以获取有关命令 IF 和IF所需的语法的帮助...ELSE条件以及建议使用哪种语法来评估分配给动态变量的先前命令/可执行文件的退出代码ERRORLEVEL该变量不是环境变量,尽管可以使用引用环境变量值的语法访问其值。

要在条件为 true 时执行的命令或命令行必须括在圆括号中,否则命令IF会将条件后的所有内容解释为要执行的参数,包括ELSE语句。

if %errorlevel% leq 1 exit 0 else exit %errorlevel%

这种情况会导致在带有01ROBOCOPY出口上执行值为0的命令EXIT。否则,如果ROBOCOPY更大1,则批处理文件处理将在下一行继续,因为else由于缺少圆括号而无法被if识别。命令 EXIT忽略退出值之后的所有内容。所以这个命令行也可以写成:

if %errorlevel% leq 1 exit 0 Batch processing exits with value 0 on condition is true.

另请参阅:

  • 内部 cmd.exe 命令设置的错误级别值是什么?
  • 哪个 cmd.exe 内部命令在成功时将错误级别清除为 0?

最新更新