Использование robocopy с Visual Studio 2010 Post-build и Pre-build events - PullRequest
30 голосов
/ 29 марта 2011

Robocopy выдает 1 при успехе, в отличие от большинства программ, которые завершаются с 0 при успехе. Visual Studio (и MSBUILD) интерпретирует код выхода 1 как ошибку.

Как Robocopy можно использовать в событиях после и до сборки Visual Studio, чтобы его сбой и успех правильно определялись средой сборки?

Примечание: это более-менее репост этого поста .

Ответы [ 7 ]

22 голосов
/ 31 октября 2012

Добавление этого ответа на запрос.На основе решения Асафа и добавления комментария скреббела.

Вы можете упростить проверку до:

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

Как любезно отмечено в комментариях, вы можете настроить «1»:зависит от того, что ваша операция должна воспринимать как ошибку.Посмотрите на значение битов, которые в комбинации составляют число, возвращаемое робокопией :

0 × 10 Серьезная ошибка.Robocopy не копировал никаких файлов.Это либо ошибка использования, либо ошибка из-за недостаточных прав доступа к исходным или целевым каталогам.

0 × 08 Не удалось скопировать некоторые файлы или каталоги (произошли ошибки копирования и превышен предел повторных попыток).Проверьте эти ошибки далее.

0 × 04 Обнаружены некоторые несоответствующие файлы или каталоги.Изучите выходной журнал.Уборка, вероятно, необходима.

0 × 02 Обнаружены некоторые дополнительные файлы или каталоги.Изучите выходной журнал.Может потребоваться некоторая уборка.

0 × 01 Один или несколько файлов были успешно скопированы (то есть новые файлы поступили).

0 × 00 Не было ошибок, и копирование не производилось,Деревья каталогов источника и назначения полностью синхронизированы.

19 голосов
/ 29 марта 2011

С , - это источник и цель копирования, а - параметры 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
9 голосов
/ 25 октября 2014

Простая проверка кода выхода 1 неверна, так как любой код выхода ниже 8 не ошибочен :

Любое значение больше 8 указывает, что был хотя бы один сбой во время операции копирования.

(Просто чтобы уточнить, код выхода 8 также является ошибкой: Several files did not copy)

Правильный код должен выглядеть следующим образом:

IF %ERRORLEVEL% GEQ 8 exit 1
exit 0
4 голосов
/ 11 ноября 2015

Синтаксически это версия для каждой строки, которая работает непосредственно на этапах 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

Рекомендации:

4 голосов
/ 29 марта 2011

MSBuild extensionpack содержит задачу Robocopy, которую вы можете использовать в процессе сборки.
Может ли это быть решением вместо событий VS до / после сборки?

Если таквы можете расширить процесс сборки Visual Studio , переопределив цели BeforeBuild, AfterBuild и вызвав задачу Robocopy (вы можете также переопределить другие цели, если они лучше соответствуют вашим потребностям, см. список в связанном MSDNpage)
Таким образом, на самом деле вам следует скачать и установить пакет расширений MSBuild, а затем открыть файл csproj / vbproj вашего проекта и отредактировать его следующим образом:

Добавление следующих записей для импорта задачи Robocopy пакета расширений MSBuild

<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>
0 голосов
/ 03 января 2019

Принятый ответ - ИМО.В Robocopy уже определены коды выхода , поэтому мы можем обычно принимать любое значение 8 или меньше, что указывает на то, что все прошло хорошо.

"Любое значение больше 8указывает на то, что во время операции копирования произошел как минимум один сбой. "

Итак, допустим, ваша команда ROBOCOPY $(Source) $(Dest) *.*, которую я буду называть $(RobocopyBinCommand).

В Visual Studio для вашего события перед сборкой или после сборки нажмите раскрывающийся список и выберите <Edit...>

Создайте новую строку под вашей командой, поместите IF %ERRORLEVEL% LEQ 8 EXIT 0, затем примените и закройтеокно свойств, например:

example

Расширенные требования кода выхода

Допустим, вы хотите, чтобы сборка прошла, только если ROBOCOPY вернется 1 или 3.Приведенная выше проверка if не позволит вам даже использовать OR -подобное поведение, поддерживаемое CMD.exe, для устранения проблемы.Вы можете обойти это ограничение несколькими способами, но я думаю, что это один из самых лаконичных способов сделать это.мы передаем результат вывода уровня ошибки в findstr, который ищет 1 или 3. Нам не нужно беспокоиться о значениях, имеющих 3 или 1, таких как 23 или 16 потому что первая оценка гарантирует, что значение равно 3 или меньше.После того, как эта оценка пройдена, если она действительно проходит, она передает уровень ошибки на findstr, который затем сравнивает уровень ошибки с 1 или 3.Если либо обнаружен findstr, findstr выйдет 0, в противном случае это не так.Если уровень ошибки не был равен 3 или меньше, уровень ошибки останется неизменным, и задача сборки выйдет из режима обычного использования 1 из ROBOCOPY.

0 голосов
/ 09 апреля 2018

Я обнаружил, что запускать robocopy гораздо проще, чем пытаться вызвать его в линию с Visual Studio.Таким образом, Visual Studio не заботится о коде возврата из robocopy.

start robocopy . ..\latestbuild

Единственное отличие, которое я мог видеть, это то, что вы увидите, что командная строка появляется и исчезает для выполнения команды robocopy.

Использование call вместо start фактически не открывает командную строку и, что еще лучше, перенаправляет вывод из robocopy в окно вывода Visual Studio.

call robocopy . ..\latestbuild

По некоторым причинам этот подход работает только при использовании в командной строке событий Pre-build.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...