Use ClickOnce technology and smart clients to extend the reach of traditional Windows Forms applications. The process involves some wizard-based configuration and minimal code.
Windows Forms (also known as a fat client) applications traditionally have provided a rich UI experience, but difficulty of deployment has limited their reach. Without sophisticated deployment software, deploying a Windows Forms application to thousands of desktops has been a daunting feat. This is in part why Web-based applications have proliferated during the past several years. Web applications reach a mass audience by removing installation requirements.
Although rich UIs can be constructed as browser-based applications, they are often more complex to create and quickly become browser specific. This has led to the rich-versus-reach debate that architects face when designing applications. The idea of the smart client evolved from the desire for both the rich client experience of a Windows Forms application and the reach of Web applications.
Windows Forms applications already have the rich UI. The reach component to provide deployment is what has been missing, and ClickOnce provides this infrastructure. The Microsoft Patterns and Practices team released a .NET Framework 1.1 preview of ClickOnce in the form of the Updater Application Block. It allows you to detect, download, and apply application updates that are deployed from a central location through a pull model by which the client self-updates. It also includes samples that demonstrate how to deploy the code within your application.
Microsoft has simplified the Updater Application Block and evolved it into ClickOnce, which is included with the Microsoft .NET Framework 2.0, and the wizard functionality included with Visual Studio 2005. ClickOnce can be applied to Windows Forms or console applications.
How ClickOnce Works
The concept behind ClickOnce deployment is fairly straightforward. You start by building your Windows Forms or console application through the software development lifecycle process of your choice. Once completed, you publish your application to a deployment server, which can be either a Web server or network file share. (You also can use some other removable media such as a CD, but this article focuses on more automated methods for auto updating.) The end result is an application that is available for initial install from the published location.
Two XML manifest files control ClickOnce: the application manifest and the deployment manifest. The application manifest describes the assemblies, dependencies, application files, and required permissions, as well as the location where updates will be available. The deployment manifest contains information on the version of the application that clients should be running and the location of the application manifest. You can generate both XML manifests using the Publish Wizard in Visual Studio 2005 or the manifest generation tool (mage.exe or mageui.exe) in the .NET Framework SDK. Each updated version of the application updates the application and deployment manifests as well. The manifest files and all of the application files are copied to the deployment location.
ClickOnce deployment operates in either launched or installed mode. Launched mode is similar to no-touch deployment in .NET 1.x, where nothing is installed locally and the application must be connected to the installation source every time the application runs. It is similar to Web applications and is best used when the application is used infrequently. Installed mode allows the application to operate even when it is disconnected from the installation source. This is the more traditional and common installation.
As previously stated, to make your application available, you publish it to a Web server, network file share, or removable media such as CD. The Publish Wizard in Visual Studio 2005 makes this a relatively straightforward process. Figures 1–4 illustrate publishing to a UNC file share.
Figure 1: Where to Publish
Figure 2: How Users Install
Figure 3: Control Application Available Offline or Not
Figure 4: Ready to Publish
Additionally, an HTML page is generated to provide a simple way for users to access and install your application (see Figure 5). You can e-mail users a link to the HTML page to make it easy for them to deploy.
Figure 5: Sample Generated Page
If you don't have access to Visual Studio 2005 and the Publish Wizard, you can use the manifest generation tool (mageui.exe) to generate a manifest (see Figure 6). It is more complicated to generate the initial manifests, but certainly better than trying to create them without assistance.
Figure 6: MageUI Screenshot
Checking for Updates
You can choose from several basic strategies to update your application. The following options are available:
- Checking for updates during application startup: This strategy works best for high-bandwidth network connections. Low-bandwidth connectivity will likely cause long delays that force the user to wait.
- Checking for an updated manifest file on a background thread after the application starts: This strategy works best for low-bandwidth network connections. If an update is available, the user is asked whether he or she wants to download the update the next time the application starts. This is the default strategy.
- Providing a UI for manual checking: This strategy works best when you want the user to control when the application is updated. It involves using ClickOnce APIs to program your own update.
- Blocking update checking to prevent the application from ever looking for updates: This strategy works when you want to initially deploy your application through ClickOnce, but have no desire to provide future updates.
The update strategy is controlled through the deployment manifest file. For instance, you block update checking by removing the <subscription> tag from the deployment manifest file. The following are some example deployment manifest files:
Checking for Updates after Startup
<!-- Check for updates after startup -->
<expiration maximumAge="4" unit="hours" />
Checking for Updates on Startup
<!-- Check for updates on startup -->
Making an Update Mandatory
<!-- Forcing an Update -->
<deployment install="true" minimumRequiredVersion="18.104.22.168">
The easiest way I have found to control the manifest files is by first generating them through the Publish Wizard in Visual Studio 2005 and then using MAGE to update them (see Figure 7). This reduces the likelihood that you will have to manually edit the manifest files.
Figure 7: Controlling Updates Through MAGE
ClickOnce Lessons Learned the Hard Way
A number of my colleagues have gone through some ClickOnce trials and tribulations, from which they learned the following lessons:
- MageUI.exe is actually the GUI for the manifest generation tool. Mage.exe is the command-line tool. Mage.exe will open MageUI.exe if no parameters are specified.
- If the build type (debug or release) or the target platform changes, it breaks compatibility with older versions of the manifest.
- Programmatically using the ClickOnce namespace will require more than the minimum level of .NET trust for the executable.
- Content files and referenced assemblies from the GAC (Global Assembly Cache) are not automatically included in the deployment.
- You can select the "Sign the ClickOnce manifests" option in project properties. This will verify that files are copied/downloaded intact. However, this prevents changing config files without resigning with Mage.
ClickOnce Enables Smart Clients
You now have a general idea of how to use ClickOnce to help enable smart client applications. You covered the background of ClickOnce and walked through an example deployment to a network file share. You also took a brief look at the manifest generation tool. Although the use of security permissions within the installation is beyond the scope of this article, I suggest you learn the security settings before using ClickOnce.
The topic of the next column is yet to be determined. If you have something in particular that you would like to see explained here, e-mail me at firstname.lastname@example.org.