Search code examples
windowsbatch-filerobocopyerrorlevel

Avoid robocopy to reset errorlevel in batch


Our compilation system copies binary dependencies using robocopy. For example, an hypotetical copy_dependencies.bat file can be something like:

@echo off
robocopy %PARAMETERS% src_path\Debug   dst_path\Debug   dep_name.dll
robocopy %PARAMETERS% src_path\Release dst_path\Release dep_name.dll

Since such binaries do not affect the success of the compilation but the execution of final executables, we'd like to add error-checking to them (check path or filenames changes, for example). The idea is to catch them ASAP instead of on a deeper level when the tests run.

As if the batch returns a non-zero errorlevel then our compilation system automatically stops, our first approach would be to check the error level at the end of each batch:

@echo off
robocopy %PARAMETERS% src_path\Debug   dst_path\Debug   dep_name.dll
robocopy %PARAMETERS% src_path\Release dst_path\Release dep_name.dll

if errorlevel 8 exit /b
exit /b 0

Note: We check for an errorlevel of at least 8 since smaller values are just warnings for us (extra files and so on). That's why we also reset the errorlevel to 0 at the end.

The problem is that robocopy resets the errorlevel, so if the first command fails it is not reported. Then, the next solution would be to check every single call:

@echo off
robocopy %PARAMETERS% src_path\Debug   dst_path\Debug   dep_name.dll
if errorlevel 8 exit /b
robocopy %PARAMETERS% src_path\Release dst_path\Release dep_name.dll
if errorlevel 8 exit /b

exit /b 0

The problem here is that we'd have to change hundreds of files.

In addition to a replace-all-like script to do so, is there any cleaner way to do it? Something like a flag to robocopy that we can add to PARAMETERS to avoid the reset?

A different approach may involve an execution flag for batches that automatically exits the script if the errorlevel is 8 or higher (so we can set it at the beginning of the compilation).


PS

I'm publishing our best solution so far but it still will require modifying all the files. Changing the batch files (especially because of the easy pattern) is not very time consuming now but I would like to know if there is a solution that does not involve such change. Thanks!


Solution

  • UPDATE

    As suggested by @DodgyCodeException in the comments, the solution that best solves this problems seems to be to prefix every robocopy statement with a single-line condition so that the robocopy is executed only if the error level has not been raised before. The copy_dependencies.bat shown in the example is now:

    @echo off
    if not errorlevel 8 robocopy %PARAMETERS% src_path\Debug   dst_path\Debug   dep_name.dll
    if not errorlevel 8 robocopy %PARAMETERS% src_path\Release dst_path\Release dep_name.dll
    
    if errorlevel 8 exit /b
    exit /b 0
    

    Previous solution included using an intermediate batch (called here my_robocopy.bat) that propagates the error level:

    @echo off
    if errorlevel 8 exit /b
    robocopy %PARAMETERS% %*
    exit /b
    

    The copy_dependencies.bat shown in the example is now:

    @echo off
    call %COMMON_PATH%\my_robocopy.bat src_path\Debug   dst_path\Debug   dep_name.dll
    call %COMMON_PATH%\my_robocopy.bat src_path\Release dst_path\Release dep_name.dll
    
    if errorlevel 8 exit /b
    exit /b 0