Wednesday, May 11, 2011

Automating ClickOnce Installations for .NET 4.0 Applications

One sign of a mature development group is the ability and willingness to automate application builds and deployments. While a variety of tools help us build our assemblies (MSBuild, NAnt, etc.), and other tools help us manage those builds (Team Foundation Server, CruiseControl.NET, etc.), a lot of time can be spent implementing the deployment side of that automation. This article is designed to assist those endeavoring to create ClickOnce deployments for their applications, focusing on those require the Microsoft .NET 4.0 Framework.

About ClickOnce

We use the Mage (Manifest Generation and Editing Tool) executable to create our ClickOnce deployment. This program is shipped with the Windows SDK, and can be found under [Program Files]\Microsoft SDKs\Windows\v[X.X]\Bin, where [Program Files] may vary based on your PC or server OS, and [X.X] is the SDK version – Windows 7 shipped with 7.0A, but at the time of this writing, 7.1 is available.

An important point is that if you are deploying applications for .NET 2.0, 3.0, or 3.5, you should use the executable found in the SDK Bin folder. However, if you are deploying a .NET 4.0 application, you need to use Mage.exe located in the NETFX 4.0 Tools sub-folder.

A ClickOnce deployment has 3 critical parts:

  1. The application files, which include all necessary executables, libraries, resource files, and configuration files.
  2. The application manifest, which is an XML file describing the application files. This file will typically be named YourProgram.exe.manifest.
  3. The deployment manifest, which is an XML file describing the application, manifest, version, and update instructions. This file will typically be named YourProgram.application

You will find that if you generate a ClickOnce deployment from the Visual Studio IDE, it creates an HTML landing page, a Setup executable, and all of your application files are appended with the .deploy extension. The landing page and Setup.exe are created as a matter of convenience, but they are unnecessary when creating your ClickOnce deployment. The .deploy extensions lead to a discussion about your specific environment.

Environment Considerations

The users and locations of your application will dictate how your environment is set up, and how your deployment behaves. Remember, a ClickOnce deployment contains your application executable, DLLs, .config files, and many other items which will be available to your users from a website or file share. Typically, these items are prevented by IIS from being downloaded.

If you are deploying to an intranet site, you will probably have more control over the IIS site that serves up the deployment, specifically the MIME types and file mappings. If you are deploying to an Internet site, or if the deployment will be hosted by the same website as another ASP.NET application or web service, you will not want the user to be able to view or download .config files! This scenario is why it can be helpful to rename your deployed assets with the .deploy extension.

ClickOnce Deployment Overview

An important consideration is how your files will be physically situated. If you will be upgrading the application periodically, and you want to take advantage of ClickOnce auto-updates, placement of the manifest files is very important. For clarity and organization, it is helpful to place your application files in a versioned sub-folder of the installation site.

For this example, we will assume the following:

  • The user will access the ClickOnce installer on a public-facing website,
  • The physical directory of the website is C:\Website\Installs\.
  • The build directory is C:\Builds\YourProgram\.
  • The ClickOnce application will auto-upgrade, if a new version is detected.

At first, we are going to create a new ClickOnce deployment for YourProgram version 1.0.0, and publish that installation. The Mage.exe statements can be run at the command line, but you can also use that to create your MSBuild or NAnt script to call the executable.

Preparing the ClickOnce Deployment

After your build process has compiled the necessary components and assemblies, they will need to be copied or moved to a working location. Remember to include the configuration file, resource files, and, if you want, an application icon file. For this example, these files are copied to C:\Builds\YourProgram\1.0.0\.

Your assemblies and executable need to be strong-named, or signed with a strong-name key file, at compile time. You can modify the project file to sign the assembly with the following lines (in the top <PropertyGroup/> section):


In the executable project file, for WPF or WinForms applications, you may also need to add the following lines to the same <PropertyGroup/> section, which can also be created via the project properties:


The manifest key file will also be used to sign your ClickOnce deployment. For development, you can create a temporary self-signed certificate, which will expire in a year from the time of generation.

Create a New Application Manifest

To create the application manifest file YourProgram.exe.manifest, execute the following:

mage.exe -New Application
         -ToFile C:\Builds\YourProgram\1.0.0\YourProgram.exe.manifest
         -Name "YourProgram by YourCompany v1.0.0"
         -FromDirectory C:\Builds\YourProgram\1.0.0
         -IconFile appicon.ico
         -UseManifestForTrust true
         -TrustLevel FullTrust
         -Publisher "YourCompany, Inc."
         -Processor x86|x64|msil

If the application manifest was built without error, it will be found at C:\Builds\YourProgram\1.0.0\YourProgram.exe.manifest.

Sign the Application Manifest

The generated application manifest must be signed with a certificate, which you will have created yourself, or received from a certificate authority:

mage.exe -Sign C:\Builds\YourProgram\1.0.0\YourProgram.exe.manifest
         -CertFile C:\Artifacts\YourCompany.pfx
         -Password password

Append .deploy Extension to Application Files

Once the application manifest is generated, you can append the .deploy extension to all application files, excluding the manifest file. This will allow the files to be downloaded from an IIS website without modifying MIME types or file mappings.

Create a New Deployment Manifest

The application manifest will now be used to generate the deployment manifest YourProgram.application:

mage.exe -New Deployment
         -ToFile C:\Builds\YourProgram\YourProgram.application
         -Name "YourProgram by YourCompany v1.0.0"
         -AppManifest C:\Builds\YourProgram\1.0.0\YourProgram.exe.manifest
         -Publisher "YourCompany, Inc."
         -AppCodeBase 1.0.0\Coll.UI.WPF.MediNexus.exe.manifest
         -Install true
         -Processor x86|x64|msil

Notice that the deployment manifest file has been created in the directory above the application manifest file’s directory. While the file can be generated to any physical location, when the set of files (application files, application manifest, and deployment manifest) is deployed to the install website, the deployment manifest will reside in the parent directory of the deployed version. This makes upgrades more straightforward (and obvious).

Modifying the Deployment Manifest File

Unfortunately, before we can sign the deployment manifest file, we must content with several short-comings with the Mage executable. First, unlike the MageUI application that also accompanies the Windows SDK, we must modify the deployment manifest to indicate that the application files are aliased with the .deploy extension. Secondly, if we want to force the ClickOnce installation to be upgraded automatically when the application is launched, we must also make that modification within the deployment manifest.

If you edit the YourProgram.application file with a text editor, you will see the <deployment/> element looks like this:

  <deployment install="true" minimumRequiredVersion="">
<expiration maximumAge="0" unit="days" />
<deploymentProvider codebase="" />

So that ClickOnce is alerted to the .deploy aliased files, we will add the mapFileExtensions=”true” attribute to the <deployment/> element. Then, to force ClickOnce to check for and install newer versions prior to launching the application, we replace the <expiration/> element with the <beforeApplicationStartup/> element. The <deployment/> element should look now like this:

  <deployment install="true" mapFileExtensions="true" minimumRequiredVersion="">
<beforeApplicationStartup />
<deploymentProvider codebase="" />

Signing the Deployment Manifest

Just like the application manifest, the deployment manifest must be signed:

mage.exe -Sign C:\Builds\YourProgram\YourProgram.application
         -CertFile C:\Artifacts\YourCompany.pfx
         -Password password

Publishing the ClickOnce Installation

Because of how the application files have been assembled, and the manifest files generated, publishing the installation is trivial. Copy the versioned folder C:\Builds\YourProgram\1.0.0 and the deployment manifest file C:\Builds\YourProgram\YourProgram.application to the website physical directory, C:\Website\Installs. In the real world, you will be copying or FTPing to your web servers. Once you direct your users to, they will be able to install and run the application!

You will likely need to upgrade your deployed application in the future. Luckily, installed copies will check the deployment manifest to see if the version has been changed, and ClickOnce handles the rest.

No comments:

Post a Comment