First, a little history. Originally we signed our application like this:
signcode /spc C:mycredencials.spc /v a:myprivatekey.pvk /t http://timestamp.verisign.com/scripts/timstamp.dll c:\Project1.exe
The problem is that it required us to enter a password in a dialog box every time this command was run. Since we built several applications at a time, our "automated" build process required a lot of manual intervention.
The solution to that problem was to embed the key in the registry using PVKIMPRT.
The command line for signcode that directly accessed the certificate store was:
signcode -cn "Cool Corp" -n "My Application" -i http://www.example.com/MyApp.html -t http://timestamp.verisign.com/scripts/timstamp.dll c:\Project1.exe
This worked well on Windows XP, but failed on Vista with the error "failed to build the certificate chain." [Update 7/25/2008 - This problem was probably caused because the intermediate key was not installed. See my later post.]
Recent discussions about codesigning seem to advocate using signtool instead of signcode, although there's no discussion about the difference. I found that signtool has one big advantage over signcode: it can read PFX files, which is what Internet Explorer exports (Control Panel / Internet Options / Content / Certificates / Export). However, if you export your certificate to a PFX file in Windows Vista, you are required to provide a password, which didn't play well with one of our automated build tools.
The first solution was to use Windows XP to create the PFX file instead of Vista. WinXP will allow you to export your certificate and private key to a PFX file without a password. However, I found a better solution with a little research.
Signtool can automatically select a code signing certificate from the registry with the /a option. That's very handy. Eventually I ended up with this command in the Post Build Event:
$(SolutionDir)Tools\SignTool sign /a /d "My Application" /du "http://www.example.com/MyApp.html" /t http://timestamp.verisign.com/scripts/timstamp.dll $(TargetPath)