【问题标题】:Post-Build Event using robocopy suddently stopped working使用 robocopy 的构建后事件突然停止工作
【发布时间】:2021-05-15 03:34:33
【问题描述】:

我对使用 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

错误显示在 Visual Studio 中:

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)"

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

【问题讨论】:

  • 使用 Robocopy 不要以反斜杠结束源路径或目标路径,并且始终使用引号来保护文件路径中的空格和特殊字符。 robocopy "C:\some\source\path" "D:\to\destination\path"
  • 我强烈建议您不要为变量分配引号。变量赋值的最佳实践是set "Dir2018=C:\Program Files\Rune\Altem 2018\Plugins\"。这使用引号来保护变量赋值,但不会使引号与变量的值分开。然后,当您需要使用变量时,请在其周围使用引号。 if not exist "%Dir2018%IssueCreator" mkdir "%Dir2018%IssueCreator".
  • 该错误是因为您的源目录未正确引用。使用脚本的所有详细输出更新您的问题,包括所有 robocopy 消息。

标签: batch-file robocopy post-build-event


【解决方案1】:

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

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 变量 Configuration 的字符串值被 Visual Studio 替换,例如在第一和第二个命令行中替换为 Debug2019。出于这个原因,第二行使用字符串 Debug2019 定义了环境变量 ConfigNumber

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

对于最后一个命令行,关于 ROBOCOPY 的两个事实,除了在命令提示符窗口中运行robocopy /? 的使用帮助输出和robocopy 的Microsoft 文档和关于@987654322 的SS64 文章@和ROBOCOPY Exit Codes

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

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

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

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

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

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

没有必要使用命令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

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

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

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

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

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

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

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

另见:

【讨论】:

    猜你喜欢
    • 2022-01-10
    • 1970-01-01
    • 2016-03-03
    • 1970-01-01
    • 2017-08-22
    • 2021-02-01
    • 2016-12-29
    • 2018-05-09
    • 2015-12-07
    相关资源
    最近更新 更多