首页 > 解决方案 > 使用 robocopy 的构建后事件突然停止工作

问题描述

我对使用 robocopy 的构建后事件有疑问。该代码用于几天前工作,现在它在我的任何项目中都不起作用。下面是我用于构建后事件的代码,用于为同一应用程序的不同构建创建插件。

根据 Squashman 和 Mofi 的建议编辑:

echo Configuration: $(Configuration)
 
set "Dir2018=C:\Program Files\Rune\Altem 2018\Plugins\"
set "Dir2019=C:\Program Files\Rune\Altem 2019\Plugins\"
set "Dir2020=C:\Program Files\Rune\Altem 2020\Plugins\"
 
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 Files\Rune\Altem 2018\Plugins\"
set "Dir2019=C:\Program Files\Rune\Altem 2019\Plugins\"
set "Dir2020=C:\Program Files\Rune\Altem 2020\Plugins\"
 
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:\Users\username\OneDrive\_WORK FILES\_REPOS\nw_issuecreator\nw_issuecreator\SnoopTool\bin\Debug2019\ "%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:\Users\username\OneDrive\_WORK FILES\_REPOS\nw_issuecreator\nw_issuecreator\SnoopTool\bin\Debug2019\" "%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:\Users\username\OneDrive\_WORK FILES\_REPOS\nw_issuecreator\nw_issuecreator\SnoopTool\bin\Debug2019\ "%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 Files\Rune\Altem 2019\Plugins\SnoopTool" 

该行if not exist %Dir2019%$(ProjectName) mkdir %Dir2019%$(ProjectName)成功执行。如果目录不存在,它会创建目录。但是,我相信问题出在下一行robocopy $(TargetDir) %Dir2019%$(ProjectName) /XF "*.pdb" /E。我没有更改应用程序中的任何内容,这发生在我的所有项目中。这可能是关于 robocopy 工作原理的更新吗?我不知道。这里完全不解。

编辑:

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

echo Configuration: $(Configuration)
 
echo Copying results to 2019
robocopy $(TargetDir) "C:\Users\username\Documents\New folder (2)"
if %errorlevel% leq 1 exit 0 else exit %errorlevel%

:exit

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

Invalid Parameter #3 : "C:\Users\oscarramirez\Documents\New folder (2)"

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

标签: batch-filerobocopypost-build-event

解决方案


我建议批处理文件的以下代码:

echo Configuration: $(Configuration)
set "ConfigNumber=$(Configuration)"
set "ConfigNumber=%ConfigNumber:~-4%"
echo Copying results to %ConfigNumber%
%SystemRoot%\System32\robocopy.exe "$(TargetDir)\" "C:\Program Files\Rune\Altem %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%\System32\robocopy.exe "%SourceDirectory%" "C:\Program Files\Rune\Altem %ConfigNumber%\Plugins\$(ProjectName)" /XF "*.pdb" /E /R:3 /W:5

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

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

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

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

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

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

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

由于第一个事实, ROBOCOPY将目录路径末尾的反斜杠解释为转义字符。"因此ROBOCOPY"在目标路径的末尾解释为属于目标路径的文字字符,尽管目录路径根本不能包含"Microsoft 在有关Naming Files、Paths 和 Namespaces的文档中描述的字符。因此ROBOCOPY"会将直到目标参数字符串开头的所有内容都解释为源参数字符串。这显然是ROBOCOPY不需要的参数字符串解释。

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

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

无需使用命令IF检查文件复制任务的目标目录是否存在,并使用命令MKDIR on not exist创建目标目录。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

第一个命令行退出批处理文件处理,ROBOCOPY0上的退出代码退出范围为 to ,否则退出代码。071

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

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

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

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

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

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

也可以看看:


推荐阅读