Robocopyは、成功すると0で終了するほとんどのプログラムとは異なり、成功すると1を出力します。 Visual Studio(およびMSBUILD)は、終了コード1をエラーとして解釈します。
RobocopyをVisualStudioのビルド後およびビルド前のイベントで使用して、その失敗と成功がビルド環境によって正しく識別されるようにするにはどうすればよいですか?
注:これは多かれ少なかれ この投稿 の再投稿です。
MSBuild拡張パック ビルドプロセスで使用できるRobocopyタスクが含まれています。
これは、VSのビルド前/ビルド後のイベントの代わりにあなたのための解決策になることができますか?
その場合は、BeforeBuild、AfterBuildターゲットをオーバーライドし、Robocopyタスクを呼び出すことで Visual Studioビルドプロセスを拡張 できます(他のターゲットも、ニーズに合っている場合はオーバーライドできます。のリストを参照してください。リンクされたMSDNページ)
したがって、実際には、プロジェクトのcsproj/vbprojファイルを開いて次の方法で編集するよりも、MSBuild拡張パックをダウンロードしてインストールする必要があります。
MSBuild拡張パックの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>
リクエストごとにこの回答を追加します。 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×011つ以上のファイルが正常にコピーされました(つまり、新しいファイルが到着しました)。
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
8未満の終了コードは誤りではありません :のように、単に終了コード1をチェックするだけでは正しくありません。
8より大きい値は、コピー操作中に少なくとも1つの障害が発生したことを示します。
(明確にするために、8の終了コードもエラーです:Several files did not copy
)
したがって、適切なコードは次のようになります。
IF %ERRORLEVEL% GEQ 8 exit 1
exit 0
構文的には、PreBuildステップ内で直接機能するコマンドごとに1行のバージョンがあります。
(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
参照:
Visual Studioとインラインで呼び出すよりも、start robocopyを実行する方がはるかに簡単であることがわかりました。このように、VisualStudioはrobocopyからの戻りコードを気にしません。
start robocopy . ..\latestbuild
私が見ることができた唯一の違いは、robocopyコマンドを実行するためのコマンドプロンプトが表示されたり消えたりすることです。
startの代わりにcallを使用しても、実際にはコマンドプロンプトは開かず、さらに良いことに、robocopyからの出力がVisualStudioの出力ウィンドウにリダイレクトされます。
call robocopy . ..\latestbuild
何らかの理由で、このアプローチは、ビルド前のイベントコマンドラインで使用した場合にのみ機能します。
受け入れられた答えは過剰なIMOです。 Robocopyにはすでに 終了コードが定義されています があるため、通常、8
以下の値は、問題がないことを示していると見なすことができます。
"8より大きい値は、コピー操作中に少なくとも1つの障害が発生したことを示します。"
したがって、コマンドがROBOCOPY $(Source) $(Dest) *.*
であるとしましょう。これを、単に$(RobocopyBinCommand)
と呼びます。
ビルド前またはビルド後のイベントのVisualStudioで、ドロップダウンをクリックして<Edit...>
を選択します
コマンドの下に新しい行を作成し、IF %ERRORLEVEL% LEQ 8 EXIT 0
を配置してから、[プロパティ]ウィンドウを適用して閉じます。例:
ROBOCOPYが1
または3
を返した場合にのみビルドを通過させたいとしましょう。上記のif-checkでは、CMD.exeでサポートされているOR
のような動作を使用して問題を修正することもできません。この制限は複数の方法で回避できますが、これは最も簡潔な方法の1つだと思います。
if %errorlevel% LEQ 3 echo %errorlevel%|findstr "1 3"
基本的に、エラーレベルをエコーした結果をfindstr
にパイプして、1または3を探します。23
のように3または1が含まれる値について心配する必要はありません。または16
。最初の評価で値が3以下であることを確認するためです。その評価が実際に合格した場合に合格すると、エラーレベルをfindstr
にパイプし、エラーレベルを1
または3
と比較します。どちらかがfindstrによって検出された場合、findstrは0を終了します。それ以外の場合は、終了しません。エラーレベルが3以下でない場合、エラーレベルは変更されず、ビルドタスクはROBOCOPYの使用を通常どおり1終了します。