Using robocopy with Visual Studio 2010 Post-build and Pre-build events

前端 未结 7 2053
忘了有多久
忘了有多久 2021-02-05 01:59

Robocopy outputs 1 upon success, unlike most programs that exit with 0 on success. Visual Studio (and MSBUILD) interprets exit code of 1 as an error.

How can Robocopy b

相关标签:
7条回答
  • 2021-02-05 02:18

    I found that it's much easier to start robocopy rather than trying to call it in-line with Visual Studio. This way Visual Studio doesn't care about the return code from robocopy.

    start robocopy . ..\latestbuild
    

    The only difference I could see is that you will see a command prompt appear and disappear to execute the robocopy command.

    Using call instead of start actually doesn't open the command prompt and, even better, redirects the output from the robocopy to Visual Studio output window.

    call robocopy . ..\latestbuild
    

    For some reason this approach only works when used in Pre-build events command line.

    0 讨论(0)
  • 2021-02-05 02:32

    Simply checking for an exit code of 1 is incorrect, as any exit code below 8 is non-erroneous:

    Any value greater than 8 indicates that there was at least one failure during the copy operation.

    (Just to clarify, an exit code of 8 is an error as well: Several files did not copy)

    The proper code, then, should look like this:

    IF %ERRORLEVEL% GEQ 8 exit 1
    exit 0
    
    0 讨论(0)
  • 2021-02-05 02:33

    With <src>, <tgt> being the copy source and target respectfully, and <opt> being robocopy options:

    robocopy <opt> <src> <tgt>
    set rce=%errorlevel%
    if not %rce%==1 exit %rce% else exit 0
    

    For instance, if we want to copy the project target to c:\temp, without retries and with all sub-directories (empty or not), we'd use:

    robocopy /R:0 /E $(TargetDir) c:\temp
    set rce=%errorlevel%
    if not %rce%==1 exit %rce% else exit 0
    
    0 讨论(0)
  • 2021-02-05 02:34

    MSBuild extensionpack contains a Robocopy task that you can use in your build process.
    Can this be a solution for you instead of VS pre/postbuild events?

    If so, you can extend the Visual Studio Build Process by overriding the BeforeBuild, AfterBuild targets and calling the Robocopy task (you can override other targets as well if they would suit your needs better, see the list in the linked MSDN page)
    So actually you should download and install MSBuild extensionpack than open your project's csproj/vbproj file and edit the following way:

    Adding following entries for importing MSBuild extensionpack's Robocopy task

    <PropertyGroup>
        <TPath>$(MSBuildExtensionsPath32)\ExtensionPack\4.0\MSBuild.ExtensionPack.tasks</TPath>        
    </PropertyGroup>
    <Import Project="$(TPath)"/>
    

    Overriding BeforeBuild, AfterBuild and executing the Robocopy task

    <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>
    
    0 讨论(0)
  • 2021-02-05 02:37

    Syntactically here is a one-line-per-command version that works directly within the PreBuild steps:

    (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
    

    References:

    • @OhadSchneider answer for GEQ 8
    • This answer on why exit 0 needs to be at the end.
    0 讨论(0)
  • 2021-02-05 02:38

    The accepted answer is overkill IMO. Robocopy already has its exit codes defined, so we can usually assume any value of 8 or less indicates things went well.

    "Any value greater than 8 indicates that there was at least one failure during the copy operation."

    So let's say your command is, ROBOCOPY $(Source) $(Dest) *.*, which I'll just refer to as $(RobocopyBinCommand).

    In Visual Studio for your Pre-Build or Post-Build Event, click the dropdown and select <Edit...>

    Create a new line below your command, and place IF %ERRORLEVEL% LEQ 8 EXIT 0 then apply and close the Properties window, eg:

    Advanced Exit Code Requirements

    Let's say you only want the build to pass if ROBOCOPY returns 1 or 3. The if-check above won't allow you to even use the OR-like behavior supported by CMD.exe to fix the issue. You can work around this limitation multiple ways but I think this is one of the most concise ways to do it.

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

    One-Liner Explanation

    Basically, we're piping the result of echoing the errorlevel to findstr which is looking for either a 1 or a 3. We don't have to worry about values that have a 3 or a 1 in them like 23 or 16 because the first evaluation makes sure the value is 3 or less. Once that evaluation passes if it does indeed pass it then pipes the errorlevel to findstr which then compares errorlevel to 1 or 3. If either is detected by findstr, findstr will exit 0, otherwise it will not. If the errorlevel was not 3 or less, errorlevel will remain unchanged and the build task will exit 1 as-usual from using ROBOCOPY.

    0 讨论(0)
提交回复
热议问题