We have a project in Visual Studio 2010 that runs a batch file in the post-build event. That batch calls to signtool.exe from Microsoft SDK to sign and timestamp the binary.
Timestamp servers (we use http://timestamp.verisign.com/scripts/timstamp.dll), however, tend to be unreliable for some reason, failing sometimes. This caused build to fail.
We implemented a more advanced batch script then (based on this code), splitting signing and timestamping, and allowing to retry the timestamp operation, if it failed.
Here is a simplified version of the batch 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
And the post-build event code would look like:
signfile.bat "$(OutDir)$(TargetName)$(TargetExt)"
So, if the timestamping fails, it retries 10 times with 2-seconds intervals.
But, what we observed was, if the timestamping went fine from the first attempt, everything was OK. However, if the first attempt failed, then the whole post-build event failed with code -1, even though the timestamping succeeded on the next try.
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 ==========
So, as you can see, even though the error code returned from signfile.bat is 0, Visual Studio thinks it is -1 and fails the event.
All attempts to clear the error flag, like adding ver>nul
here and there, or adding exit 0
in the end (certainly with adding "call" before signfile.bat) didn't help since it seemed like Visual Studio checked not just for errorlevel but also for something else. In fact, the batch as well as signfile.bat only return 0 or 1 in case of error, but not -1. And if signtool.exe returns an error once, it seems like there is no way to convince Visual Studio not to fail the post-build event.