Uso de robocopy con eventos de Post-compilación y Pre-compilación de Visual Studio 2010


Robocopy produce 1 si tiene éxito, a diferencia de la mayoría de los programas que salen con 0 si tiene éxito. Visual Studio (y MSBUILD) interpreta el código de salida de 1 como un error.

¿Cómo se puede usar Robocopy en eventos post y pre - construcción de Visual Studio de tal manera que su error y éxito sean identificados correctamente por el entorno de construcción?

Nota: esto es más o menos un repost de este post.

Author: Ohad Schneider, 2011-03-29

6 answers

MSBuild extensionpack contiene una tarea Robocopy que puede usar en su proceso de compilación.
¿Puede esto ser una solución para usted en lugar de VS pre/postbuild eventos?

Si es así, puede extender el proceso de compilación de Visual Studio invalidando los objetivos BeforeBuild, AfterBuild y llamando a la tarea Robocopy (también puede invalidar otros objetivos si se adaptan mejor a sus necesidades, consulte la lista en la página de MSDN vinculada)
Así que en realidad usted debe descargar e instalar MSBuild extensionpack que abra el archivo csproj / vbproj de su proyecto y edite de la siguiente manera:

Agregar las siguientes entradas para importar la tarea Robocopy de MSBuild extensionpack

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

Sobreescribir BeforeBuild, AfterBuild y ejecutar la tarea 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>
 4
Author: János Nagy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-29 11:27:13

Con , siendo el origen y el destino de la copia respetuosamente, y siendo las opciones de robocopy:

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

Por ejemplo, si queremos copiar el objetivo del proyecto a c:\temp, sin reintentos y con todos los subdirectorios (vacíos o no), usaríamos:

robocopy /R:0 /E $(TargetDir) c:\temp
set rce=%errorlevel%
if not %rce%==1 exit %rce% else exit 0
 19
Author: Asaf R,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-29 10:07:38

Añadiendo esta respuesta por solicitud. Basado en la solución de Asaf, y añadiendo el comentario de skrebbel.

Puede simplificar la comprobación a:

robocopy <opt> <src> <tgt>
if %errorlevel% leq 1 exit 0 else exit %errorlevel%

Como se comentó amablemente en los comentarios, es posible que desee ajustar el '1': Depende de lo que su operación debe tratar como un error. Echa un vistazo a el significado de los bits que en combinación conforman el número devuelto por robocopy :

0×10 Error grave. Robocopy no copió ningún archivo. Esto es o bien un error de uso o un error debido a privilegios de acceso insuficientes en el directorios de origen o destino.

0×08 Algunos archivos o directorios no se pueden copiar (errores de copia se produjo y se excedió el límite de reintentos). Compruebe estos errores adicional.

0×04 Se detectaron algunos archivos o directorios que no coincidían. Examinar la registro de salida. El servicio de limpieza es probablemente necesario.

0×02 Se detectaron algunos archivos o directorios adicionales. Examine la salida registro. Algunas tareas de limpieza pueden ser necesario.

0×01 Uno o más archivos se copiaron correctamente (es decir, archivos nuevos han llegado).

0×00 No se produjeron errores y no se realizó ninguna copia. La fuente y los árboles de directorios de destino están completamente sincronizados.

 18
Author: mafu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-20 22:33:41

Simplemente verificar un código de salida de 1 es incorrecto, ya que cualquier código de salida por debajo de 8 no es erróneo :

Cualquier valor mayor que 8 indica que hubo al menos un fallo durante la operación de copia.

(Solo para aclarar, un código de salida de 8 también es un error: Several files did not copy)

El código apropiado, entonces, debería verse así:

IF %ERRORLEVEL% GEQ 8 exit 1
exit 0
 9
Author: Ohad Schneider,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-25 15:58:43

Sintácticamente aquí hay una versión de una línea por comando que funciona directamente dentro de los pasos 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

Referencias:

 4
Author: crokusek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:25:52

Descubrí que es mucho más fácil iniciar robocopy en lugar de intentar llamarlo en línea con Visual Studio. De esta manera Visual Studio no se preocupa por el código de retorno de robocopy.

start robocopy . ..\latestbuild

La única diferencia que pude ver es que verá un símbolo del sistema aparecer y desaparecer para ejecutar el comando robocopy.

Usando call en lugar de start en realidad no abre el símbolo del sistema y, mejor aún, redirige la salida de robocopy a la ventana de salida de Visual Studio.

call robocopy . ..\latestbuild

Por alguna razón, este enfoque solo funciona cuando se usa en la línea de comandos de eventos previos a la compilación.

 0
Author: Menol,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-09 08:44:31