Monday, July 13, 2015

Signing ClickOnce WPF application

So let's say you have a WPF application that you want to distribute using ClickOnce. Like I am doing with my Visual Task Map.

If you want your users to download and run your application without going through multiple scary red dialog windows with warnings, you need to sing it.

A lot of information on this topic is scattered all over the web. Microsoft has a good set of articles about it. There are bunch of answered questions on Stack Overflow. But sometimes you just want the short version. So here it is.


  1. To sing any code you need to buy a code signing certificate
  2. Update project settings to sign and timestamp the ClickOnce manifest.
  3. Add a BeforePublish target into your project to sign the executable before it becomes part of the ClickOnce package.
I am using Comodo timestamping server - http://timestamp.comodoca.com/authenticode, but there are plenty of other servers to chose from. For example you can use this one: http://timestamp.verisign.com/scripts/timstamp.dll. It does not make any difference, any timestamping server will work.

Signing the manifest is simple as you just go o the project properties, Signing tab, and use your certificate (the one that you just bought, the one that has the private key) to sign the manifest. That is also where you can specify the timestamping server that will be used to timestamp the manifest.

You might also assume that signing the executable is as easy as signing the manifest because there is one more checkbox in the same dialog that says "Sign the assembly". You would be wrong. This is where you provide a certificate, used to create a Strong Name for your assembly, and your awesome new certificate won't work. Also, you don;t actually care about the strong-naming your executable. This is a good article about the difference between what VS does and what you need.

So how do you sing the executable ? There are no easy project options that will allow you to do that. And when you are dealing with ClickOnce, it all becomes a bit more complicated as ClickOnce sources binaries from the Obj folder, not the usual Bin folder, and the executable in the Obj folder has to be signed precisely at the right time: after it was actually built, but before the ClickOnce publishing mechanism has picked it up.

You can read more details about this here, and then here.
But the short version is that you need to add a call to singtool.exe into your project file. Something like this:
<Target Name="BeforePublish" Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
  <Exec Command=""C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\signtool.exe" sign /n "My Name" /t http://timestamp.comodoca.com/authenticode $(ProjectDir)obj\$(ConfigurationName)\$(TargetFileName)" />
</Target>

One important thing to remember is that the BeforePublish action works incorrectly with WPF applications in VS2013 RTM (and AfterCompile option did not work for me either). But this problem has been resolved in VS2013 Update 4 - be sure to install it.

No comments: