我们在 Visual Studio 2010 中有一个项目,它在构建后事件中运行批处理文件。该批处理从 Microsoft SDK 调用 signtool.exe 以对二进制文件进行签名和时间戳记。
然而,时间戳服务器(我们使用http://timestamp.verisign.com/scripts/timstamp.dll )由于某种原因往往不可靠,有时会失败。这导致构建失败。
然后我们实现了一个更高级的批处理脚本(基于此代码),拆分签名和时间戳,并允许在失败时重试时间戳操作。
这是批处理脚本 (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)"
因此,如果时间戳失败,它会以 2 秒的间隔重试 10 次。
但是,我们观察到的是,如果时间戳从第一次尝试开始就很好,那么一切都很好。但是,如果第一次尝试失败,那么整个构建后事件将失败,代码为 -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之前添加“call”)都没有帮助,因为看起来Visual Studio不仅检查了错误级别,还检查了一些东西别的。实际上,批处理和 signfile.bat 仅在出错时返回 0 或 1,而不是 -1。如果 signtool.exe 一次返回错误,似乎没有办法说服 Visual Studio 不要让构建后事件失败。