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