ClickOnce Applications and Manifest Signing
I’ve recently had to integrate ClickOnce publishing of an application with an automated build and deployment process, and wanted to briefly chat about some of the headlines to watch out for if you need to do this in future.
There are two manifest files required for ClickOnce publishing - a deployment manifest, and an application manifest. The first very simple thing… the deploy manifest is named .application and the application manifest is named blah.exe.manifest. You might be tempted to think that the .application file is the application manifest, but not so.
The project I’m working on has multiple environments that we deploy to, and we’re distributing and updating the ClickOnce application from a website. This means that the deploy manifest can only be generated once you know the environment that you’re deploying to, as it contains the URL to check for updates etc.
In addition, the manifest files have to be signed before the ClickOnce application can be downloaded and installed. This means you have a choice…
- Either you have to generate appropriate manifests upfront for each environment that you might wish to deploy to, and sign each. This would occur while packaging up a release
- Alternatively, you have to ship the pfx certificate for signing in the release package, then generate and sign the manifests once you know which environment you’re deploying to as part of the installation
The second option is a little more flexible, but requires mage.exe (from the Framework 2 SDK) to be available on the install machine. In addition it means the signing certificate is kicking around in the release package, so obviously this is only appropriate for server software where the release and install setup is secure. I do have other justification for why I think this is ok - ask if you’re interested.
There are 2 msbuild tasks available to create the manifest files - GenerateApplicationManifest and GenerateDeploymentManifest. The task provided to sign a manifest takes a certificate thumbprint, which ties up to a cert in the local certificate store. This is not particularly useful, so it’s easier to write a lightweight msbuild wrapper around the mage utility, which can sign a manifest from a given pfx file. An example would be… mage.exe -sign ManifestName -CertFile PfxFilePath -pwd PfxPassword. If you want to generate the pfx to use in signing, take a look at makecert and pvk2pfx.
Be very careful about sequence - you need to generate the application manifest, sign the application manifest, then generate the deploy manifest, and finally sign the deploy manifest. If you generate both the manifests, then sign both, the publishing will fail. Basically the deploy manifest contains the public key token from the application manifest, so the application manifest must be signed prior to generating the deploy manifest.
Unless you need them, you don’t need to worry about the bootstrapper (setup.exe) or the versioned subfolders generated if you publish manually. The main thing is to have the deploy manifest pointing to the current version.
I also found the generated webpage for hosting the application to be quite bloated, so wrote my own. All you need to do is provide a hyperlink to the .application file, and clicking will trigger the ClickOnce runtime to download and install the application.
Phew. Think that’s it for now.
5 Comments
1 GP(MPK) says...
Is there any way to re-sign any of the .deploy files?
So, OK, my ClickOnce app has a dynamic Web (service) Reference, whose default string eventually shows up in the .exe.config.deploy file. Now, the default string varies per deployment location, so I have to edit this file once it is published. The problem is, once I edit this file, its hash gets suddenly corrupt and then fistful of hair suddenly gets pulled from their orifices.
So, alright, I’ll just re-sign them, right? Unfortunately, attempting to re-sign these .deploy files (with mage -Sign) doesn’t seem to work (despite msdn’s examples).
Any idea how I can get out of this quagmire?
Thanks,
GP
(Posted at 6:26 pm on August 28th, 2007)
2 GP(MPK) says...
Sorry, but I figured out how to do it:
1) manually edit the *.deploy file (in my case, the *.config.deploy file)
2) re-sign the .manifest file
3) update the .application file using mage w/ the re-signed .manifest file
4) re-sign the .application file
5) ???
6) profit!
(Posted at 1:56 pm on August 29th, 2007)
3 Oli says...
Sorry I didn’t read in time! Good to hear that you got to the bottom of it.
I think these kind of scenarios must actually be quite common, but the ClickOnce material I found didn’t seem to discuss the details.
(Posted at 1:05 pm on August 31st, 2007)
4 GP(MPK) says...
Indeed. The thing that I neglected to emphasize in my previous post is that the order of the steps matter. Seems like a bottom-to-top re-sign approach(i.e., .deploy, then .manifest, then .application) ensures that everything is linked up correctly (as opposed to top-to-bottom).
Anyway, I’m hoping that the google-bots picks this up so that someone else won’t have to go through what I did.
(Posted at 5:44 pm on August 31st, 2007)
5 Back2Nature says...
Hi, the Yahoo!search picks this up for me
I am using VS VB Express 2008. My problem is that the generated blah.exe.manifest file has threadingModel=”apartment” instead of
threadingModel=”Apartment”.
1. Can I do something to correct this?
2. A way is to edit and re-sign it, but I don’t have mage.exe or mageui.exe. How can I have them?
3. Any other way to re-sign?
Thanks!
(Posted at 4:04 am on September 17th, 2008)