Делать сценарии событий до и после сборки красивыми? - PullRequest
11 голосов
/ 07 июня 2011

У меня есть несколько умеренно здоровенных сценариев событий до и после сборки для моих проектов Visual Studio 2008 (на самом деле это в основном сценарии событий после сборки).Они работают нормально, так как работают правильно, и когда я exit 0, сборка завершается успешно, а когда я exit 1, сборка завершается с ошибкой.Однако эта ошибка огромна и выглядит примерно так:

The command "if Release == Debug goto Foo
if Release == Release goto Bar
exit 0

:Foo
mkdir "abc"
copy "$(TargetDir)file.dll" "abc"
[...]
" exited with code 1.

Вы поняли идею.Весь сценарий всегда выгружается как часть описания ошибки.Весь сценарий также выгружается в окно вывода во время сборки.Итак, почему я видел в Интернете различные ссылки на использование echo в этих сценариях?Например, вот часть примера на одном конкретном сайте:

:BuildEventFailed
echo POSTBUILDSTEP for $(ProjectName) FAILED
exit 1
:BuildEventOK
echo POSTBUILDSTEP for $(ProjectName) COMPLETED OK

Есть ли способ заставить Visual Studio подавить весь вывод скрипта, кроме того, что echo ed (и, следовательно, с использованием echoимеет смысл выводить только то, что вы хотите), или эти примеры просто ошибочны, и они не понимают, что весь сценарий всегда сбрасывается?

Ответы [ 3 ]

8 голосов
/ 08 июня 2011

ОК - суть проблемы в том, что движки сборки Visual Studio C ++ и C # совершенно разные.

Механизм сборки C ++ выполняет пакетный код, указанный в событии «Командная строка» до или после сборки проекта без выгрузки фактического кода в окно «Вывод»; он просто выводит то, что echo отредактировано кодом, а также то, что отсылается командами, которые выполняет код (например, '2 file (s) copyed') команды copy и т. д.) Примеры I ' мы видели в Интернете, предположительно, предназначенные для движка сборки Visual Studio C ++, потому что на самом деле не нужно ничего выводить с движком сборки C #, если вы помещаете свой пакетный код C # до или после сборки в событие проекта C # окно командной строки.

Это потому, что механизм сборки C #, который я использовал, делает сбросить весь код в этом поле в окно вывода. Более того, если код завершается ошибкой, он включает весь блок кода в этом поле в сообщении об ошибке, которое появится в «Списке ошибок» - механизм сборки C ++ этого не делает (подробнее об этом позже).

Лучшее решение, которое я нашел, поэтому состоит в том, чтобы минимизировать объем кода, который вы помещаете в окно командной строки проекта C # до или после сборки. Все, что вы там поместите, будет сброшено в окно вывода при его выполнении. Лучший способ минимизировать код - это просто запустить пакетный файл и передать необходимые аргументы в пакетный файл. Содержимое пакетного файла НЕ будет сбрасываться в окно «Вывод», но (как и в случае с кодом в «Командной строке» для механизма сборки C ++) echo будет выводиться и выводиться из команд, которые выполняет код пакетного файла; Это хороший способ управления выводом скрипта C # до или после сборки. Затем механизм сборки C ++ обрабатывает код, указанный в поле «Командная строка», так же, как механизм C # обрабатывает код в командном файле; он не выводит сам код, а только вывод кода.

Таким образом, в основном, если вы компилируете проект C ++ в Visual Studio, вы можете просто поместить весь пакетный сценарий в поле «Командная строка», и он не будет выгружен в окно «Вывод». Однако при компиляции проекта C # я рекомендую поместить ваш пакетный скрипт в отдельный файл .bat и просто вызвать этот файл с соответствующими аргументами из поля командной строки событий до или после сборки. Я получил окно командной строки события C # после сборки, которое выглядело так:

..\..\BuildScripts\PostBuild.bat $(ConfigurationName) $(ProjectName) "$(TargetDir)" "$(ProjectDir)"

... и мой файл PostBuild.bat выглядит так:

@REM Store args...
set _configName=%1%
set _projectName=%2%

@REM Remove quotes from remaining args...
set _targetDir=###%3%###
set _targetDir=%_targetDir:"###=%
set _targetDir=%_targetDir:###"=%
set _targetDir=%_targetDir:###=%

set _projectDir=###%4%###
set _projectDir=%_projectDir:"###=%
set _projectDir=%_projectDir:###"=%
set _projectDir=%_projectDir:###=%

if %_configName% == Release goto StartProcessing
echo No post-build processing required.
exit 0

@REM Start post-build processing
:StartProcessing
echo Starting post-build processing.

@REM use input args to do batch script work, such as:
copy "%_targetDir%*.dll" "%_projectDir%..\..\..\..\..\CommonAssemblies"
if errorlevel 1 goto CopyFailure

@REM etc.

goto PostBuildSuccess

@REM Failure labels
:CopyFailure
echo Post-build processing for %_projectName% FAILED: Failed to copy file(s) to common assemblies directory!
exit 1

@REM Post-build success
:PostBuildSuccess
echo Post-build processing for %_projectName% completed OK.
exit 0

Это намного более аккуратно управляет выводом, и только то, что echo ed в этом пакетном скрипте, будет выводиться в окно вывода.

Наконец, как уже упоминалось выше, механизмы сборки C # и C ++ также выводят разные вещи в сообщении об ошибке, которое появляется в «Списке ошибок», когда сбой обработки после сборки (т. Е. Пакетный код завершается с кодом, отличным от *) 1026 *). Механизм сборки C ++ всегда, кажется, просто говорит:

Error result 1 returned from 'C:\Windows\system32\cmd.exe'.

Механизм сборки C #, тем не менее, будет включать все содержимое поля командной строки события до или после сборки (в зависимости от того, что не удалось) в сообщении об ошибке, например ::

The command "..\..\BuildScripts\PostBuild.bat Release MyProject "C:\Development\MyProject\bin\" "C:\Development\MyProject\"" exited with code 1.

Все еще немного глотка для одного сообщения об ошибке, но гораздо более управляемым, чем включение всего кода, который мы переместили в пакетный файл, в сообщение об ошибке!

Несмотря на это, было бы неплохо иметь возможность настроить это сообщение об ошибке, которое появляется в списке ошибок, для отображения чего-то, что я определяю. Я сомневаюсь, что это возможно, но если кто-нибудь знает способ сделать это, пожалуйста, не стесняйтесь публиковать его как комментарий!

5 голосов
/ 07 июня 2011

Если вы поместите свои скрипты в пакетный файл, VS будет молчать об этом.Когда вам нужен доступ к $ (projectName) и т. Д., Вы должны будете передать их как параметры в пакетный файл.Я искал настройки, которые могут повлиять на вывод, но не смог их найти.

Протестировано с этим пакетным файлом (d: \ test.bat); @ echo off даже не требуется:

@echo off
echo "I'm Gonna Fail"
exit 1

Установите Pre-Build Event->Command Line на d: \ test.bat , оставьте Description пустым (описаниечто показано вместо Выполнение события предварительной сборки ... . В VS2008 я получаю это в окне вывода сборки для проекта C ++:

Performing Pre-Build Event...
"I'm Gonna Fail"
Project : error PRJ0002 : Error result 1 returned from 'C:\Windows\system32\cmd.exe'.

Для проекта C #,это показано вместо этого (с MSBuild verbosity, установленным на normal ):

Target PreBuildEvent:
  d:\test.bat
  "I'm gonna fail"
  Microsoft.Common.targets(895,9) error MSB3073: The command "d:\test.bat" exited with code 1.
1 голос
/ 08 мая 2018

@ Джез, ваш ответ отличный, но я бы улучшил командный файл следующим образом: Используя% ~ 1, он будет легче удалять кавычки из аргументов:

@echo off
if "%~1"=="" (set ErrorMessage=Parameter 1 missing. It has to be the Config name. & GOTO :EndError)
if "%~2"=="" (set ErrorMessage=Parameter 2 missing. It has to be the Project name. & GOTO :EndError)
if "%~3"=="" (set ErrorMessage=Parameter 3 missing. It has to be the Targetdir. & GOTO :EndError)
if "%~4"=="" (set ErrorMessage=Parameter 4 missing. It has to be the Projectdir. & GOTO :EndError)

cd /D "%~dp0"  &:: setting current directory to there where the batchfile is.

:: With ~ the quotes are removed
set _configName=%~1 
set _projectName=%~2
set _targetDir=%~3
set _projectDir=%~4
set _outDir=%~5

rd Plugins\%_projectName% /S /Q
if errorlevel 1 (set ErrorMessage=remove directory failed!!. & GOTO :EndError)
md Plugins\%_projectName%
if errorlevel 1 (set ErrorMessage=make directory failed!!. & GOTO :EndError)
xcopy %_targetDir%* Plugins\%_projectName% /E /Q
if errorlevel 1 (set ErrorMessage=Copy failed!!. & GOTO :EndError)

exit 0

:EndError
echo --! Error in %~nx0 !-- 
echo %ErrorMessage%
pause
exit 1
...