Question

Robocopy sortit 1 après succès, contrairement à la plupart des programmes qui sortent avec 0 sur le succès. Visual Studio (et MSBuild) interprète le code de sortie de 1 comme erreur.

Comment utiliser Robocopy dans les événements Visual Studio après et pré-construction de sorte que son échec et son succès sont correctement identifiés par l'environnement de construction?

Remarque: c'est plus ou moins un republi ce post.

Était-ce utile?

La solution

MSBUILD ExtensionPack Contient une tâche de robocopie que vous pouvez utiliser dans votre processus de construction.
Cela peut-il être une solution pour vous au lieu des événements pré / post / post-constructeur?

Si oui, vous pouvez étendre le processus de construction Visual Studio En remplaçant le préalable, des cibles Afterbuild et en appelant la tâche de robocopie (vous pouvez également remplacer d'autres cibles s'ils répondaient mieux à vos besoins, consultez la liste dans la page MSDN liée)
En fait, vous devez télécharger et installer MSBuild ExtensionPack que d'ouvrir le fichier CSPROJ / VBPROJ de votre projet et modifier la manière suivante:

Ajout des entrées suivantes pour l'importation

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

Remplacer avant la construction, la construction et l'exécution de la tâche de robocopie

<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>

Autres conseils

Ajout de cette réponse par demande. Basé sur la solution d'ASAF et ajoutant le commentaire de Skrebbel.

Vous pouvez simplifier le chèque à:

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

Comme aimablement remarqué dans les commentaires, vous voudrez peut-être ajuster le «1»: cela dépend de ce que votre opération devrait traiter comme une erreur. Jettes un coup d'oeil à La signification des bits qui en combinaison constituent le nombre renvoyé par Robocopy:

0 × 10 Erreur grave. Robocopy n'a copie aucun fichier. Il s'agit d'une erreur d'utilisation ou d'une erreur due à des privilèges d'accès insuffisants sur les répertoires source ou de destination.

0 × 08 Certains fichiers ou répertoires n'ont pas pu être copiés (des erreurs de copie se sont produites et la limite de réessayer a été dépassée). Vérifiez ces erreurs davantage.

0 × 04 Certains fichiers ou répertoires disposés ont été détectés. Examiner le journal de sortie. L'entretien ménager est probablement nécessaire.

0 × 02 Certains fichiers ou répertoires supplémentaires ont été détectés. Examiner le journal de sortie. Certains entretiens ménagères peuvent être nécessaires.

0 × 01 Un ou plusieurs fichiers ont été copiés avec succès (c'est-à-dire que de nouveaux fichiers sont arrivés).

0 × 00 Aucune erreur ne s'est produite et aucune copie n'a été effectuée. Les arbres de répertoire source et de destination sont complètement synchronisés.

Avecu003Csrc> ,u003Ctgt> étant la source de copie et la cible respectueusement, etu003Copt> Être des options de robocopie:

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

Par exemple, si nous voulons copier la cible du projet sur C: Temp, sans tentatives et avec tous les sous-répertoires (vides ou non), nous utiliserions:

robocopy /R:0 /E $(TargetDir) c:\temp
set rce=%errorlevel%
if not %rce%==1 exit %rce% else exit 0

La simple vérification d'un code de sortie de 1 est incorrecte, car Tout code de sortie en dessous de 8 est non errone:

Toute valeur supérieure à 8 indique qu'il y a eu au moins une défaillance pendant l'opération de copie.

(Juste pour clarifier, un code de sortie de 8 est également une erreur: Several files did not copy)

Le code approprié devrait donc ressembler à ceci:

IF %ERRORLEVEL% GEQ 8 exit 1
exit 0

Syntaxiquement, voici une version d'une ligne par commande qui fonctionne directement dans les étapes de prébuild:

(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

Références:

J'ai trouvé que c'est beaucoup plus facile de début Robocopy plutôt que d'essayer de l'appeler en ligne avec Visual Studio. De cette façon, Visual Studio ne se soucie pas du code de retour de Robocopy.

start robocopy . ..\latestbuild

La seule différence que je pouvais voir est que vous verrez une invite de commande apparaître et disparaître pour exécuter la commande robocopy.

Utilisant appel à la place de début En fait, n'ouvre pas l'invite de commande et, mieux encore, redirige la sortie de la fenêtre de sortie de Robocopy à Visual Studio.

call robocopy . ..\latestbuild

Pour une raison quelconque, cette approche ne fonctionne que lorsqu'elle est utilisée dans la ligne de commande des événements pré-construction.

La réponse acceptée est exagérée IMO. Robocopy a déjà son codes de sortie définis, nous pouvons donc généralement supposer toute valeur de 8 ou moins indique que ça s'est bien passé.

"Toute valeur supérieure à 8 indique qu'il y a eu au moins une défaillance pendant l'opération de copie."

Alors disons que votre commande est, ROBOCOPY $(Source) $(Dest) *.*, que je vais simplement appeler $(RobocopyBinCommand).

Dans Visual Studio pour votre événement pré-construction ou post-construction, cliquez sur la liste déroulante et sélectionnez <Edit...>

Créez une nouvelle ligne sous votre commande et placez-vous IF %ERRORLEVEL% LEQ 8 EXIT 0 Ensuite, appliquez et fermez la fenêtre Propriétés, par exemple:

example

Exigences de code de sortie avancées

Disons que vous voulez que la construction ne passe que si Robocopy revient 1 ou 3. L'IF-Check ci-dessus ne vous permet pas même d'utiliser le OR- Comportement comme soutenu par CMD.exe pour résoudre le problème. Vous pouvez contourner cette limitation plusieurs manières, mais je pense que c'est l'une des façons les plus concises de le faire.

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

Explication à une ligne

Fondamentalement, nous édifions le résultat de l'écho de l'erreur findstr qui est à la recherche d'un 1 ou d'un 3. Nous n'avons pas à nous soucier des valeurs qui ont un 3 ou un 1 en eux comme 23 ou 16 Parce que la première évaluation s'assure que la valeur est de 3 ou moins. Une fois que cette évaluation passe si elle la passe effectivement findstr qui compare ensuite Errorlevel à 1 ou 3. Si l'un ou l'autre est détecté par Findstr, Findstr quittera 0, sinon il ne le fera pas. Si level Errorlevel n'était pas 3 ou moins, ErrorLevel restera inchangé et la tâche de construction quittera 1 comme l'habitude de l'utilisation de la robocopie.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top