Событие PostBuild завершилось с ошибкой в ​​Visual Studio после ошибки SignTool.exe

У нас есть проект в Visual Studio 2010, который запускает командный файл в событии после сборки. Эта партия вызывает signtool.exe из Microsoft SDK для подписания и отметки времени в двоичном формате.

Серверы Timestamp (мы используем http://timestamp.verisign.com/scripts/timstamp.dll), однако по какой-то причине они ненадежны, иногда сбой. Это привело к сбою сборки.

Мы реализовали более продвинутый пакет script, затем (на основе этого кода), разделив подпись и отметку времени и позволив повторить операцию метки времени, если она не удалась.

Вот упрощенная версия пакета script (signfile.bat):

@echo off

REM sign the file...
signtool.exe /f Authenticode.pfx /p PASS %1

if %errorlevel% neq 0 exit /b %errorlevel%

set timestamp_server=http://timestamp.verisign.com/scripts/timstamp.dll

for /L %%a in (1,1,10) do (

    REM try to timestamp the file...
    signtool.exe timestamp /t %timestamp_server% %1

    if errorlevel 0 if not errorlevel 1 GOTO succeeded

    REM wait 2 seconds...
    ping -n 2 127.0.0.1 > nul
)

REM return an error code...
echo signfile.bat exit code is 1.
exit /b 1

:succeeded
REM return a successful code...
echo signfile.bat exit code is 0.
exit /b 0

И код события после сборки будет выглядеть так:

signfile.bat "$(OutDir)$(TargetName)$(TargetExt)"

Итак, если временная отметка не удалась, она повторяет 10 раз с интервалом в 2 секунды.

Но, что мы наблюдали, было, если временная отметка прошла с первой попытки, все было в порядке. Однако, если первая попытка не удалась, то событие post-build завершилось с кодом -1, даже если при попытке повторить эту попытку удалось выполнить следующую попытку.

1>------ Build started: Project: myproject, Configuration: NonOptimized x64 ------
1>  Done Adding Additional Store
1>  Successfully signed: E:\tfs\MySolution\bin\x64\NonOptimized\myproject.dll
1>  
1>EXEC : SignTool error : The specified timestamp server either could not be reached
1>  or returned an invalid response.
1>    This may happen if you specify an RFC 3161 timestamp URL but used
1>    the /t option or you specified a legacy Authenticode timestamp URL
1>    but used the /tr option.
1>EXEC : SignTool error : An error occurred while attempting to timestamp: E:\tfs\MySolution\bin\x64\NonOptimized\myproject.dll
1>  
1>  
1>  Number of errors: 1
1>  
1>  Successfully timestamped: E:\tfs\MySolution\bin\x64\NonOptimized\myproject.dll
1>  
1>  signfile.bat exit code is 0.
1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(113,5): error MSB3073: The command "signfile.bat "E:\tfs\MySolution\bin\x64\NonOptimized\myproject.dll"
1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(113,5): error MSB3073: :VCEnd" exited with code -1.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Итак, как вы можете видеть, хотя код ошибки, возвращаемый из signfile.bat, равен 0, Visual Studio считает, что это -1 и не удается выполнить событие.

Все попытки очистить флаг ошибки, например добавление ver>nul здесь и там, или добавление exit 0 в конце (конечно, с добавлением "вызова" перед signfile.bat) не помогло, так как это казалось Visual Studio проверен не только на уровень ошибок, но и на что-то еще. Фактически, пакет, а также signfile.bat возвращают только 0 или 1 в случае ошибки, но не -1. И если signtool.exe возвращает ошибку один раз, кажется, что нет возможности убедить Visual Studio не вызывать событие post-build.

Ответы

Ответ 1

Проведя много времени на экспериментирование и поиск, найдите статью , упомянутую здесь в комментарии. Похоже, Visual Studio сканирует выход, ищет некоторые специальные ключевые слова. Signtool.exe выводит среди других EXEC : SignTool error : An error occurred, которые кажутся достаточно, чтобы предупредить Visual Studio о том, что произошла ошибка.

Итак, предлагаемое решение состояло в том, чтобы перенаправить выходные и потоки ошибок в nul как 2>nul 1>nul. Уровень ошибок по-прежнему будет установлен, поэтому вы сможете выяснить, произошла ли ошибка. Но вам может потребоваться распечатать дополнительные сообщения, чтобы увидеть статус:

REM try to timestamp the file...
signtool.exe timestamp /t %timestamp_server% %1 2>nul 1>nul

if errorlevel 0 if not errorlevel 1 (
    echo Successfully timestamped: %1
    GOTO succeeded
)
echo Timestamping failed for %1

Теперь Visual Studio довольна:

1>------ Build started: Project: myproject, Configuration: NonOptimized x64 ------
1>  Done Adding Additional Store
1>  Successfully signed: E:\tfs\MySolution\bin\x64\NonOptimized\myproject.dll
1>  
1>  Timestamping failed for "E:\tfs\MySolution\bin\x64\NonOptimized\myproject.dll"
1>  Successfully timestamped: "E:\tfs\MySolution\bin\x64\NonOptimized\myproject.dll"
1>  signfile.bat exit code is 0.
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

На самом деле просто добавить 2>nul было бы достаточно, чтобы исправить это. Поток ошибок все равно будет напечатан: Number of errors: 1, но это не вызывает проблемы.