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
あちこちに追加する、または最後に追加する (確かに signfile.bat の前に「call」を追加する) など、エラー フラグをクリアしようとするすべての試みは、exit 0
Visual Studio が errorlevel だけでなく何かもチェックしたように見えたため、役に立ちませんでしたそうしないと。実際、バッチと signfile.bat は、エラーの場合に 0 または 1 のみを返しますが、-1 は返しません。また、signtool.exe が 1 回エラーを返した場合、ビルド後のイベントが失敗しないように Visual Studio を説得する方法はないようです。