簡體   English   中英

在Visual Studio 2010后期構建和預構建事件中使用robocopy

[英]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返回13 上面的if-check將不允許您甚至使用CMD.exe支持的類似OR的行為來解決問題。 您可以通過多種方式解決此限制,但我認為這是最簡潔的方法之一。

if %errorlevel% LEQ 3 echo %errorlevel%|findstr "1 3"

單線解釋

基本上,我們將回顯errorlevel的結果傳遞給尋找1或3的findstr 。我們不必擔心其中包含3或1的值,如2316因為第一個評估確保值為3或更小。 一旦該評估通過,如果確實通過了它,則將errorlevel傳遞給findstr ,然后將findslevel與13進行比較。 如果findstr檢測到任何一個,則findstr將退出0,否則將退出。 如果errorlevel不是3或更小,則errorlevel將保持不變,並且構建任務將像往常一樣使用ROBOCOPY退出1。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM