[英]Using robocopy with Visual Studio 2010 Post-build and Pre-build events
Robocopy在成功時輸出1,與大多數成功退出0的程序不同。 Visual Studio(和MSBUILD)將退出代碼1解釋為錯誤。
如何在Visual Studio后期和預構建事件中使用Robocopy,以便構建環境正確識別其失敗和成功?
注意:這或多或少是這篇文章的轉貼 。
根據請求添加此答案。 基於Asaf的解決方案,並添加skrebbel的評論。
您可以將檢查簡化為:
robocopy <opt> <src> <tgt>
if %errorlevel% leq 1 exit 0 else exit %errorlevel%
正如評論中所說的那樣,您可能需要調整“1”:這取決於您的操作應該視為錯誤。 看一下組合構成robocopy返回的數字的位的含義 :
0×10嚴重錯誤。 Robocopy沒有復制任何文件。 由於源或目標目錄上的訪問權限不足,這可能是使用錯誤或錯誤。
0×08無法復制某些文件或目錄(發生了復制錯誤並超出了重試限制)。 進一步檢查這些錯誤。
0×04檢測到一些不匹配的文件或目錄。 檢查輸出日志。 家政可能是必要的。
0×02檢測到一些額外的文件或目錄。 檢查輸出日志。 可能需要一些家政服務。
0×01成功復制了一個或多個文件(即新文件已到達)。
0×00未發生錯誤,未進行復制。 源目標樹和目標目錄樹完全同步。
使用<src>,<tgt>作為復制源和目標,<opt>是robocopy選項:
robocopy <opt> <src> <tgt>
set rce=%errorlevel%
if not %rce%==1 exit %rce% else exit 0
例如,如果我們想要將項目目標復制到c:\\ temp,而不重試和所有子目錄(空或不),我們將使用:
robocopy /R:0 /E $(TargetDir) c:\temp
set rce=%errorlevel%
if not %rce%==1 exit %rce% else exit 0
只需檢查退出代碼為1是不正確的,因為8以下的任何退出代碼都是非錯誤的 :
任何大於8的值表示復制操作期間至少有一個失敗。
(只是為了澄清,退出代碼8也是一個錯誤: Several files did not copy
)
那么,正確的代碼應如下所示:
IF %ERRORLEVEL% GEQ 8 exit 1
exit 0
這里的語法是一個單行命令版本,直接在PreBuild步驟中工作:
(robocopy "$(ProjectDir)..\Dir1" "$(ProjectDir)Dir1" "Match.*" /a+:R) ^& IF %ERRORLEVEL% GEQ 8 exit 1
(robocopy "$(ProjectDir)..\Dir2" "$(ProjectDir)Dir2" "Match.*" /a+:R) ^& IF %ERRORLEVEL% GEQ 8 exit 1
exit 0
參考文獻:
MSBuild擴展包包含一個可在構建過程中使用的Robocopy任務。
這可以成為您的解決方案,而不是VS pre / postbuild事件嗎?
如果是這樣,您可以通過覆蓋BeforeBuild,AfterBuild目標並調用Robocopy任務來擴展Visual Studio構建過程 (如果它們更適合您的需要,您也可以覆蓋其他目標,請參閱鏈接的MSDN頁面中的列表)
所以實際上你應該下載並安裝MSBuild擴展包,而不是打開項目的csproj / vbproj文件並編輯以下方式:
添加以下條目以導入MSBuild extensionpack的Robocopy任務
<PropertyGroup>
<TPath>$(MSBuildExtensionsPath32)\ExtensionPack\4.0\MSBuild.ExtensionPack.tasks</TPath>
</PropertyGroup>
<Import Project="$(TPath)"/>
覆蓋BeforeBuild,AfterBuild並執行Robocopy任務
<Target Name="BeforeBuild">
<Message Text="Beforebuild" />
<MSBuild.ExtensionPack.FileSystem.RoboCopy Source="C:\temp\robo_src1" Destination="C:\temp\robo_dest1" Files="*.*" Options="/MIR">
<Output TaskParameter="ExitCode" PropertyName="Exit" />
<Output TaskParameter="ReturnCode" PropertyName="Return" />
</MSBuild.ExtensionPack.FileSystem.RoboCopy>
<Message Text="ExitCode = $(Exit)"/>
<Message Text="ReturnCode = $(Return)"/>
</Target>
<Target Name="AfterBuild">
<MSBuild.ExtensionPack.FileSystem.RoboCopy Source="C:\temp\robo_src2" Destination="C:\temp\robo_dest2" Files="*.*" Options="/MIR">
<Output TaskParameter="ExitCode" PropertyName="Exit" />
<Output TaskParameter="ReturnCode" PropertyName="Return" />
</MSBuild.ExtensionPack.FileSystem.RoboCopy>
<Message Text="ExitCode = $(Exit)"/>
<Message Text="ReturnCode = $(Return)"/>
</Target>
我發現啟動 robocopy要比在Visual Studio中調用它更容易。 這樣,Visual Studio不關心robocopy的返回代碼。
start robocopy . ..\latestbuild
我能看到的唯一區別是你會看到一個命令提示符出現並消失以執行robocopy命令。
使用call而不是start實際上不會打開命令提示符,更好的是,將robocopy的輸出重定向到Visual Studio輸出窗口。
call robocopy . ..\latestbuild
出於某種原因,此方法僅在預構建事件命令行中使用時才有效。
接受的答案是矯枉過正的IMO。 Robocopy已經定義了退出代碼 ,因此我們通常可以假設任何值為8
或更小都表示事情進展順利。
“任何大於8的值表示復制操作期間至少有一次失敗。”
所以假設您的命令是ROBOCOPY $(Source) $(Dest) *.*
,我將其稱為$(RobocopyBinCommand)
。
在用於預構建或后構建事件的Visual Studio中,單擊下拉列表並選擇<Edit...>
在命令下創建一個新行,並放置IF %ERRORLEVEL% LEQ 8 EXIT 0
然后應用並關閉“屬性”窗口,例如:
假設您只希望構建在ROBOCOPY返回1
或3
。 上面的if-check將不允許您甚至使用CMD.exe支持的類似OR
的行為來解決問題。 您可以通過多種方式解決此限制,但我認為這是最簡潔的方法之一。
if %errorlevel% LEQ 3 echo %errorlevel%|findstr "1 3"
基本上,我們將回顯errorlevel的結果傳遞給尋找1或3的findstr
。我們不必擔心其中包含3或1的值,如23
或16
因為第一個評估確保值為3或更小。 一旦該評估通過,如果確實通過了它,則將errorlevel傳遞給findstr
,然后將findslevel與1
或3
進行比較。 如果findstr檢測到任何一個,則findstr將退出0,否則將退出。 如果errorlevel不是3或更小,則errorlevel將保持不變,並且構建任務將像往常一樣使用ROBOCOPY退出1。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.