pplication architects often struggle with two important but competing goals. They want to write a Windows®-based rich client application that runs on the desktop because that provides the best stateful, interactive experience for the user. However, they also want to minimize the effort required to deploy and update their apps—a goal best accomplished using a thin client model. Users care about applications that are easy to use and that will not interfere with other apps on their machine.
ClickOnce, part of version 2.0 of the Microsoft® .NET Framework, allows you to deploy Windows-based rich client apps to a desktop by placing the application files on a Web or file server accessible to the client and providing the user with a link.
When the user clicks the link on a Web page or in an e-mail, the application files are downloaded to the user's machine and executed. The program executes in a secure sandbox provided by .NET code access security (CAS) limiting what it's allowed to do based on the evidence it presents. When a new version of the application is deployed to the server, it can be automatically detected by connected clients, and the update can be downloaded and applied in a variety of ways based on optional deployment settings. ClickOnce allows applications to be deployed offline as well, making the app behave as if it had been installed on the local machine.
ClickOnce relies on a number of capabilities that already exist in the .NET Framework and runtime, as well as a few new ones that will be introduced specifically for ClickOnce. To understand the security protections of ClickOnce, you need to have a good understanding of CAS. If you have been exposed to no-touch deployment in .NET 1.x, or the Updater Application Block from the Microsoft Patterns and Practices series, you will have a basic understanding of what ClickOnce can do for you. ClickOnce will be further enhanced in the next version of Windows, code-named "Longhorn," so this is a deployment model that it would be wise to get your arms around for the future.
A key goal of ClickOnce is to provide a trustworthy deployment model for users to be able to download and execute applications from centrally managed servers without requiring administrator privileges on the client machine. They are deployed in a safe manner that prevents ClickOnce deployed applications from interfering with or corrupting any other applications or data on the client. Applications deployed using ClickOnce also need to run in a secure execution context whose permissions are limited based on where the application is coming from or the trust assigned to the originator of that application.
The initial deployment model of ClickOnce is straightforward and applies to any ClickOnce application. When it comes to updating ClickOnce applications, there are a bunch of options that modify the way updates occur depending on choices that are made when the application is published to the deployment server. To clarify the terms, I will refer to the process of deploying application files to a deployment server as "publishing" the application, whereas the process of deploying application files to a client machine from the deployment server via ClickOnce mechanisms will be referred to as "deploying." To differentiate between the two types of ClickOnce applications, I will refer to applications that are deployed to support offline execution as "installed" applications, and those that can be run only while online as "launched" applications.
First Time App Deployment
The basic process to perform a first-time deployment of an application via ClickOnce is shown in Figure 1. Once the application is developed and tested, you publish the application to the deployment server. This involves simply copying all the application files into a folder on the Web or file server, along with the application and deployment manifest files that describe the deployment to the ClickOnce runtime. Once the files have been published to the deployment server, a link to the deployment manifest is provided to the user in the form of a URL (as a hyperlink or shortcut). When a user clicks on that link, the .NET runtime on the client machine will recognize the file extension and perform a ClickOnce deployment of the application, downloading and executing the application on the user's desktop.
Figure 1 ClickOnce Deployment Process
The files are downloaded to a cache under the logged-on user's profile on the local machine in an obfuscated location. The application then executes with the CAS security context determined by the location of the deployment server, such as the Internet or Local Intranet zone. You can override the default location-based policy with a custom security policy on the user's machine that depends on content-based evidence (hash, publisher, or strong name). If you have content-based evidence that matches the deployed application, the permissions of the corresponding code group will apply instead. I will discuss security protections and configuration options as I step through some of the deployment scenarios throughout the rest of this article.
If the ClickOnce application was published to be a launched application, then that is pretty much the end of the story. The user will have to launch the application using the link provided. Typically, this will be a link to a Web site, which launches the application that provides functionality related to the site's purpose. Every time the user clicks the link, the runtime on the user's machine will check the version cached locally against the version on the deployment server. If new files are available, they will be downloaded before the application is launched. The locally cached version will then be executed on the user's desktop. This is very much like no-touch deployment using .NET 1.x today.
However, if the application was published as an installed application, in addition to launching the first time the user clicks the provided link, a shortcut will be added to the Start menu (for example, Start | Programs | MyCompany | MyClickOnceApp), and the program can be launched from there in the future. Additionally, an item will be added to the Add/Remove Programs Control Panel applet to allow the user to uninstall the application, a process which simply removes the Start menu shortcut and clears the files from the cache under the user's profile. The Add/Remove Programs item will also let the user roll back to a previous version if updates have occurred.
The update story for installed applications gets a little more complicated because of the many available options. These include whether updates are checked for automatically, whether they are required, when the application checks for available updates, and whether the update is downloaded before launching the application or in the background while the app is running. Additionally, you can perform updates programmatically using the ClickOnce API and skip the automatic update mechanisms. I'll step through several of these scenarios later with the sample application.
Designing ClickOnce Applications
ClickOnce is focused on deploying presentation-tier Windows-based applications. It is not a replacement for Windows Installer (MSI) technology, nor is it suitable for all types of applications. As mentioned earlier, if a program needs to carry out privileged operations that could affect other applications or data on the target machine, such as performing unrestricted file access or accessing the registry, then it may not be suitable for deployment using ClickOnce. Additionally, if an application needs privileged access to the local machine at install time, then it is definitely not a candidate for ClickOnce deployment because by design there are no mechanisms in ClickOnce to add registry entries, install shared assemblies in the Global Assembly Cache (GAC), install services, and so on.
However, if you can design your application so that it does not need to do anything special at install time, and its primary purpose is to present a rich user interface that talks to back-end services on the network, then you have a great candidate for ClickOnce deployment. ClickOnce allows you to request additional runtime execution privileges at install time by prompting the user, and you can also deploy a trust license from a trusted license authority that will allow elevated runtime privileges without prompting the user. This allows your ClickOnce app to do meaningful things that go beyond what the default security policy would allow, but does not require an administrator to touch each client machine to deploy custom security policy every time you roll out a new application. As with the design of any application, however, you should address your security requirements early to determine whether ClickOnce is a suitable option.
Applications deployed with ClickOnce have no specific implementation requirements in the most common scenarios. You don't have to write any ClickOnce-specific code, derive from any base classes, or implement any interfaces. The basic ClickOnce capabilities are provided by the runtime, so the client application itself does not necessarily have to be aware of ClickOnce. There are optional programmatic approaches to performing updates that would require writing some ClickOnce-specific code in your application, but that only applies if the ClickOnce automatic update capabilities do not meet your requirements.
Any client machines will need to have the .NET Framework 2.0 installed on them for ClickOnce to work. When you publish a ClickOnce app, a bootstrapper setup.exe and supporting files are also published to the server, and allow you to easily deploy the .NET Framework and any other Microsoft required components, such as the Microsoft Data Access Components (MDAC), Microsoft Installer, DirectX®, and so on. However, installing those items is a privileged operation and will require administrator permissions to succeed. The server itself does not have any specific requirements and can be any kind of Web server or file server.
ClickOnce is targeted toward line of business applications such as Customer Resource Management (CRM) applications, personnel management applications (timecards, training, pay, and benefits management, contact info, and so on), or business data analysis applications. These applications typically need to present a rich interactive UI for the user, but act upon data and services that are accessed on middle-tier applications, Web servers, or database servers. They are also frequently deployed in enterprise environments in which there may be thousands of workstations, and deploying apps and updates to all of those machines is often too costly if an administrator has to perform a normal installation on each machine. ClickOnce could also potentially be used for consumer applications over the Web, such as multimedia applications, games, communications tools, and other forms of apps that do not have extensive install-time requirements, especially if those applications might have updates frequently available.
ClickOnce Sample App
The best way to get a sense of what ClickOnce can do for you is to take a walking tour by performing a number of deployments and updates using a sample application. The TimecardManager sample application allows you to enter and view time entries for working on a job or project. There are probably a few more features you would add before using it for real-world time tracking, but it's a good example of a simple application that you'd deploy to large numbers of intranet or Internet users to be available both online and offline. I will evolve the application over the course of the article from a launched application that simply stores time entries in a local file using isolated storage to a final installed application that stores entries in a database when connected and performs updates at the explicit request of the user.
I'll show you some dialogs that you will see in the Tech Preview version of Visual Studio® 2005 (formerly code-named "Whidbey") to demonstrate the basic process of publishing and updating applications. Keep in mind that these UIs will probably change significantly for the better by the time Visual Studio 2005 is released, and even by Beta 1, so don't get too wrapped up in the particular layouts and options. Focus mainly on the flow.
TimecardManager is a simple Windows Forms application consisting of a couple of forms, as shown in Figure 2. As I mentioned earlier, except for certain advanced scenarios, you do not have to write any ClickOnce-specific code within the application itself. So for the first couple versions of the TimecardManager application, I am not going to focus on the code at all.
Figure 2 A Windows Forms App
To publish this application, you need to place the compiled executable (and any supporting assemblies and resources) into a folder on the Web server or file server that you will use as the deployment server. In addition to the application files themselves, you need an application manifest and a deployment manifest. The manifest files are just XML files with a particular schema that the common language runtime (CLR) understands and can use to determine what to deploy and how to deploy it using ClickOnce.
The application manifest (.manifest file) describes the assemblies and files that comprise the application, including identity information of the assemblies (name, hash/public key token, version, and locale), application dependencies, and trust information that will affect the security policy under which the application is run. The deployment manifest (.deploy file), shown in Figure 3, contains summary information about the deployment itself, including version information, where to find the application manifest, and a number of options regarding the kind of deployment and update behavior to be performed.
You could hand-craft these files, but Visual Studio 2005 will automatically create them when you use its built-in publishing capabilities. When you select Project | Publish Project, a wizard steps you through the final options involved in actually publishing the application to a deployment server so that it can be presented to ClickOnce clients. There are additional ClickOnce options that affect the way the application will be updated, and these options can be accessed through the Project Properties dialog.
Under Configuration Properties, there are two new subsections of project settings: Security and Publish (shown in Figure 4 and Figure 5). The Security section allows you to specify which permissions the application needs to execute. These requirements get published as part of the application manifest and are used on the client to determine whether to prompt the user to allow elevated permissions for the application. If the permissions required by the application are greater than the permissions that the security policy would grant based on the application evidence, then the user will be prompted to allow the elevated permissions that the application needs to run.
In the PDC Technology Preview version, the functionality in the Security project settings is incomplete. In future versions, you will have fine-grained control to specify individual permissions that the application requires. In the Tech Preview version, you can only select from the built-in permission sets in .NET. However, you can tweak the resulting application manifest by hand after publishing, as I will do in version 2.0 of the sample application. The Publish project settings allow you to configure additional fine-grained options regarding how the application gets deployed and updated by ClickOnce, including whether the application can be run offline or online only, whether updates are required or optional, and how updates are downloaded and applied.
If you open up version 1.0 of the TimecardManager project in Visual Studio and select Project | Publish Project, you will see the Publish Wizard, which allows you to specify the location to which you want to publish the application. Typically, this location will be a Web server, but it could be a network file share, an FTP server, or a local disk path as well.
I will assume you have IIS on your development machine, so first enter a publishing location of http://localhost/appdeploy/TimecardManager. Then the wizard will confirm whether you want this application to be an installed application (available offline) or a launched application (available online only), and will match what was selected in the Publish project settings. For version 1.0 of the application, you will deploy it as a launched application. The final step just summarizes the actions that will be taken.
When you press Finish, Visual Studio 2005 will recompile the application to make sure it is up to date, and will then copy the project build outputs to the deployment server. It will also generate the appropriate application and deployment manifests based on the project settings and will place them on the deployment server as well. Finally, it will launch an instance of Microsoft Internet Explorer opened to a generated publish.htm page that contains a link to the deployment manifest so that you can test out the ClickOnce deployment process.
If you click the deployment manifest link, the client runtime checks the application information on the server and the application will launch without prompting the user. If you run the app again using the link to the .deploy file, you will see a brief flash as the runtime rechecks the application information to determine that the cached version is current, and then the application will launch again with no additional prompting.
Now that you've built, deployed, and executed your first ClickOnce application, the next logical step is to take a look at some of the update behaviors of ClickOnce. You should be aware of a couple of issues in the Technology Preview version of ClickOnce that could trip you up. First, you must have a network connection, even if you are deploying from the local machine. Second, you must close the browser that contains the publish page before publishing a new version of the application, or the caching of that page in Internet Explorer will confuse ClickOnce on the client machine.
Version 1.1 of the sample app has no additional functionality, but its deployment model is changed to an installed application instead of a launched application. You can actually version the deployment separately from the versioning of the assembly or application by changing the version attribute on the assemblyIdentity element in the .deploy file. For demonstration purposes and to have Visual Studio do the dirty work, I just bumped the version number of the assembly in the AssemblyInfo.cs file. This will also result in an updated deployment version number that matches the executable assembly version when you publish with Visual Studio. If you open version 1.1 of the TimecardManager, select Project | Publish Project, and specify the same location for the publishing server as used for version 1.0, you will see in Step 2 of the Publish Wizard that this version of the app is configured for both online and offline use.
If you launch the application using the link on the publish.htm Web page after publishing, you will see a slightly different prompt. Because this version of the application will be installed on the user's machine (meaning it adds a Start menu item and an Add/Remove Programs item), the user is prompted to confirm the installation. If you click the Install button, the application will be downloaded and run as before. If you look in the Start menu after this process, you will find a new menu group under Programs with the name of the company under which your Visual Studio environment is running. Under that will be a shortcut to the deployment manifest that lets you launch the application whether you are online or offline.
In Visual Basic® .NET projects, there is a Version section in the project properties that lets you set the company and description information that will be used for publishing. In the Technology Preview, these settings are completely separate from those specified using assembly attributes, and C# has no corresponding project properties. I would expect to see a more unified approach in later beta versions. You can always manually set the company name that the app is published under by editing the publisher attribute of the description element within the deployment manifest file after publishing to the deployment server. In fact, you can expect that administrators will want to control what goes in the deployment manifest, and tools will be made available in later releases to allow them to easily edit the settings through a GUI tool.
The ClickOnce project settings for version 1.1 of the TimecardManager specified that ClickOnce should check for application updates before the application starts. The settings also specified that application updates are required. If you are connected to the network, each time you launch version 1.1 of the TimecardManager from the Start menu shortcut, it will check the server to see if there is a new version available. If there is, it will require that you download and run that new version, otherwise the application will not be allowed to run. You will be prompted when it detects a new version, but aside from that the connected behavior with these settings is almost identical to a launched application. If you are offline, the app will just run like a normal local application.
Let's move on to yet another version of TimecardManager to demonstrate both the update behavior and some elevated permissions requirements. Version 2.0 of the application allows you to save your timecard entries to a database over the network if you are connected, as well as cache the entries in isolated storage when you are disconnected. It also puts the data access code into a separate class library assembly, so the application then consists of more than one assembly. Because it talks to a database, it will require permissions that are not part of the Local Intranet code group that is applied based on launching from a URL like http://machinename/folder/app.deploy. Note that the code group is applied at the application level, which is a new feature in version 2.0 of the .NET Framework. In version 1.x of the .NET Framework, the lowest level that code groups were applied to was the individual assembly. Because a ClickOnce application manifest provides an identity for an application as a single entity, regardless of which assemblies and files it is comprised of, security policy can be scoped to the application instead of individual assemblies.
To allow the application to obtain the permissions it needs without administrator intervention on the client machine, ClickOnce can prompt the user at installation time to ask them to grant the application the elevated permissions. Once permission is granted, the user will not be prompted again on subsequent runs. Although this capability circumvents some of the security protections provided by the CLR by allowing a user to elevate security permissions for that application, you can prevent the user from being allowed to do this through security policy in an enterprise environment. Allowing the user to elevate permissions is an important capability for applications deployed over the Internet, where no administrators may be available.
The next step is to open the project for version 2.0 of the TimecardManager and publish the project. Because the Technology Preview version of Visual Studio 2005 does not allow you to tweak the individual permissions needed by a ClickOnce-deployed application, you will have to edit the application manifest after publishing. This way, you can make it prompt for the additional database permission that this version of the application needs. You can find the application manifest in a subfolder of the location to which you published. For example, if you published to http://localhost/appdeploy/TimecardManager, the application files and manifest for version 2.0 will be located in C:/Inetpub/wwwroot/appdeploy/Timecard Manager/TimecardManager_ 22.214.171.124.
Based on the project security settings, the manifest will contain permission elements for the Local Intranet zone, but version 2.0 of the application requires the additional SqlClientPermission to make calls to the database. To do this, you add an IPermission element to the security section of the application manifest, specifying the permission type required as shown here (removing the line breaks):
<IPermission class="System.Data.SqlClient.SqlClientPermission, System.Data, Version=1.2.30703.27, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/>Once you add that element to the security element in the manifest and save it, you can launch version 1.1 of the application using the Start menu shortcut that was created at install time. When you do, the application will check the deployment server, see that a new version (2.0) is available and updates are required, and prompt you to apply the update. When you do, you will see a slightly different installation dialog confirming both installation and elevation of permissions. If you allow it to install, the app should download the updates and run version 2.0, getting the time entries from the database rather than from isolated storage. The demo application keeps it simple and works with either offline or online storage, and does not try to synchronize the two data sources. For a real-world application you would need to come up with a design to merge the locally cached time entries with those on the database server when you run in a connected mode following disconnected operations.
In later versions of the Visual Studio beta, there will be one additional way to handle elevated permissions without needing to prompt the user. In an intranet environment, you can have an administrator configure a trust license authority within the security policy on each user's machine. Once this is done, a trust license can be deployed with a ClickOnce application to elevate permissions to those required by the application without prompting the user. Basically, if the trust license comes from an authority that is already trusted by the user's machine, then the ClickOnce engine will be allowed to elevate the permissions on the user's machine based on the credentials of the trust license authority deployed with the application.
The automatic updating features in ClickOnce are very flexible and can address the vast majority of application update requirements. There may be times, though, where you want full control of how and when updates occur. Version 3.0 of the sample application does not use the automatic update features of ClickOnce at all. Instead, it uses the ClickOnce programmatic API to manually check for available updates and command those updates when necessary. In the Technology Preview, the classes that support these features live in the System.DeploymentFramework namespace. In later versions, they will be moved to System.Deployment. This namespace lives in a separate assembly, so version 3.0 of the application references System.DeploymentFramework.dll to bring in the code for updates. You can try out the by-request update feature by running version 3.0 of the TimecardManager application and selecting File | Check for Updates. The application code will use the ClickOnce API to see if any updates are available from the deployment server and, if so, will download them.
In addition to changing the update model, version 3.0 also corrects a bug that you may have noticed. Each time you updated to a new version, any records saved in isolated storage disappeared. In .NET 1.x, you only had two options for using isolated storage: isolation by user and assembly, or isolation by user and domain.
Using isolated storage for a ClickOnce application is the right thing to do because it prevents you from needing elevated file I/O permissions for many scenarios and keeps your application's files from interfering with other applications' files. However, the isolation levels available in .NET 1.x were insufficient for a ClickOnce scenario because as soon as you apply an update, the assembly and domain identity will change, and your existing application files stored in isolated storage will be orphaned. As a result, version 2.0 of the .NET Framework includes a new level of isolation: isolation by user and application. This allows files stored using this isolation level to be accessible by multiple versions of the same application, where the application version is determined by the application manifest, as opposed to the normal individual assembly versioning scheme for .NET-based applications.
To use programmatic updating, you code against the ApplicationDeployment class (previously named ApplicationUpdaterService in the Technology Preview). This class exposes several methods and properties that can help you determine whether updates are available and how to apply them. The static CurrentDeployment property will get you back an instance of the ApplicationDeployment that encapsulates information and interaction with the deployment on the client machine. When you call the CheckForUpdate method, the deployment server will be checked for an update. If one is available, you can get the new files either synchronously with the Update method or asynchronously through a separate API. Figure 6 shows the on-demand update code from the sample application.
With the Technology Preview bits, once the update is downloaded, you will need to prompt the user to restart the application for the new version to take effect. The update is simply downloaded to a separate set of folders under the user's cache and the Start menu shortcut is updated to point to that version. In later builds of Visual Studio 2005, I expect to see the ClickOnce API include a way to tell the application to shut down and restart using the new version that has just been downloaded using the API, without having to prompt the user to restart manually.
The Shape of Things to Come
I have touched on a lot of the features available in ClickOnce. Several features are not yet available, but should be by the time Visual Studio 2005 is released. I mentioned trust licenses earlier, which will allow permissions to be elevated in deployments coming from a trusted source without prompting the user. In future builds of Visual Studio 2005, XML signatures will be applied to all manifests and will be required to verify the authenticity of the deployment source and ensure that the app files have not been tampered with since they were deployed. Visual Studio 2005 will include a "Debug in zone" feature that allows you to launch a debug session in a specified security context so that you can debug the app with the permissions that it will have granted in the targeted runtime environment, such as the Local Intranet or Internet zones. It will also include a code analysis tool to determine exactly which permissions it requires so that you can truly specify the minimum set of permissions required when you deploy with ClickOnce.
ClickOnce in the next release of Windows, code-named "Longhorn," will contain further enhancements. In order to support all the platforms that the .NET Framework supports, ClickOnce in Visual Studio 2005 just uses simple file transfer mechanisms to download files. In Longhorn, ClickOnce will take advantage of the Background Intelligent Transfer Service (BITS) to allow a trickle-feed update of files in a way that is less obtrusive to the user. Additionally, the execution context in Longhorn will be very different and more robust, allowing apps to either be hosted in a browser or run externally, and they will run within a Secure Execution Environment that will provide even better protections than will be available on the .NET Framework 2.0 runtime. The new UI features of Longhorn will provide an even more compelling reason to run a Windows client instead of a browser-based application. ClickOnce will make this possible in a distributed environment. Look for other enhancements not yet announced once initial feedback on ClickOnce is obtained.
ClickOnce provides a new deployment technology that gives you the best of a rich Windows-based application user experience and the deployment and maintenance benefits of Web applications. It allows a user to download and execute a rich client application over the Web, off a network file share, or from local media, and the app can subsequently be run offline. It offers a full Windows user interface running on a desktop, while allowing single server deployment of application files and updates. Client applications are automatically deployed and updated on the user's machine from the deployment server in a safe way and will not affect other applications or data that already exist on the machine. Those applications run in a security context that can prevent them from doing malicious things at run time. ClickOnce includes a number of options that give application architects and designers a lot of flexibility in addressing real-world deployment and execution scenarios and requirements.
The power and flexibility provided by ClickOnce make it possible to use Windows client applications in many scenarios where browser-based applications are the only feasible solution. I recommend you take a close look at the capabilities of ClickOnce and consider how it can deliver your distributed application's presentation tier when Visual Studio 2005 is released. I'm certain that you'll find that ClickOnce makes updating and deploying your own applications faster, smoother, and more user friendly.