The Problem:
There is a ClickOnce application that is deployed in several environments; say for example a staging environment and a production environment. You want to install each environments application on your PC; you install the staging app by going to https://staging.url, then you install the production app by visiting https://production.url. The staging application gets replaced with the production app. You cannot have a side-by side installation of the staging and production ClickOnce application on a client PC.
A Solution:
Use different certificate files to sign the manifest files of each environment. For example we can have a “production.pfx” and a “staging.pfx” to sign the manifests of the production and staging environments respectively. By doing this now you can have side-by-side installations of the ClickOnce applications for each of your environments. In addtion to this use a different name (PublisherName) so that you’d get a different menu item to identify each environment.
Automation:
If you build your applications using visual studio itself, then changing the signing certificate file and name is one of the things you’d have to do before each build. But what if you’ve got a automated build environment, how do you do it then?
One way is to use the Manifest Generation and Editing (Mage.exe) command line tool to manually deploy the ClickOnce applications.
If you’re using CruiseControl.NET for your builds and you could do all this from the MsBuild task and pass in all the necessary changes for each environment as buildArgs. In this case we need to change the ManifestKeyFile and the ManifestCertificateThumbprint (This is the certificate thumbprint, in Visual Studio you can see this by clicking on the “more details” button on the “Signing” tab on the “Properties” page of your project)
Example of a CCNet MsBuild Task block where we change these values:
<!–Staging–>
<msbuild>
<executable>C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe</executable>
<workingDirectory>C:\MyClickOnce\</workingDirectory>
<projectFile>MyClickOnce.csproj</projectFile>
<buildArgs>/p:Configuration=Release
/p:InstallUrl=https://www.staging.url/
/p:PublisherName=”Staging App”
/p:ManifestKeyFile=”Staging.pfx”
/p:ManifestCertificateThumbprint=”9DAAADE32307C99743FC74A475D6008370C65642″
</buildArgs>
<targets>Build;Publish</targets>
<timeout>15</timeout>
</msbuild>
Following this, we’d have have another MsBuild task block to create the Production application.
If you’re into NAnt, then Neil’s blog post on ClickOnce deployment using NAnt should get you started. I hope this helps someone, or points to some direction of a way of achieving a side-by-side ClickOnce installations of multiple environments.
Your post solved my problems. I have been trying to install demo/test/prod ClickOnce versions side-by-side… your simple suggestion of switching the sign files worked. Keep on rockin’, dood.
Could you please elaborate on switching the sign files. Should we remove the staging.pfx file and add production.pfx before production deployment ?
HI KK,
You solution can contain all the .pfx files. The .pfx files aren’t deployed with the ClickOnce app. They are used to sign application and deployment manifests.
So, all you need to make sure is that you’re using different .pfx files for each environment when you’re publishing the ClickOnce app.
To select .pfx files in Visual Studio:
Properties -> Signing -> Check “Sign the ClickOnce manifest” -> Select from File
If you’ve got only one .pfx file you can create as many certificates as you want using “Create Test Certificate”
Hope this helps
Hey nice post,
I have pfx which requires password. Could you plaese provide me the parameter that i can use to pass password for my pfx file.
Thanks,
Divyesh.
Hi Divyesh,
You could do something like:
mage -Sign ClientShell.manifest -CertFile companyPFX.pfx -Password pa$$word
see: http://cs.blueberryislandmedia.com/blogs/blueberries/archive/2009/04/24/clickonce-deployment-via-command-line-with-makecert.aspx
———-
I haven’t tried this myself, but the other thing you could try is to use the certificate off the certificate store. To do this,
1) Import the certificate to the certificate store (it will ask for the password here),
2) Only specify the /p:ManifestCertificateThumbprint value and specify /p:ManifestKeyFile=”" as blank.
———-
Hope this helps