Beta 2 is the time in a release cycle when Microsoft traditionally finalizes the feature set of a product and assess which new features are going to make it into the final product. As stated in last month’s article, the Visual C++ IDE team has a much heavier workload than the IDE teams associated with the managed-code-only compilers. Consequently, not all the features that the CLR introduces and the other IDE teams implement will be available in C++ in the same timeframe.
For Whidbey release, the IDE team has spent a large amount of time making IntelliSense a reliable and high-performance part of the IDE. This focus on IntelliSense has necessitated cuts in other areas, and the Class Designer (covered in Part 2 of this series) and ClickOnce IDE support have been cut. Dealing with the lack of IDE support for ClickOnce is not a major issue (more on that shortly), but the removal of the Class Designer is a real shame for C++ developers who were looking forward to the introduction of a built-in modeling and documentation tool. A number of third-party offerings are available in this area, however. A future article will cover these.
The popularity of Web applications can be attributed to two key advantages that they over their non-browser-based competitors: the ability to offer the application to clients on any platform and the simplified deployment model. In many corporate scenarios, the cross-platform issue is not a major consideration because the group of machines that the application will be deployed on is tightly controlled. Still, deployment and update issues can outweigh the benefits offered by a traditional rich-client application. Microsoft has recognized that deployment and updates are a major issue for traditional applications, and has made significant efforts to allow .NET Windows Forms to share the distribution qualities that have made ASP.NET so successful.
These efforts have resulted in the Updater Application Block, available as part of the Microsoft Patterns and Practices Enterprise Library, which allows applications to automatically update themselves by pulling newer versions of their assemblies from a remote file share or Web server. In .NET 2.0, these concepts have been extended further with a new technology called ClickOnce. ClickOnce incorporates the concepts of Web applications, XCOPY deployment, and the Updater Application block to deliver a model for rich-client (or, to use Microsoft’s new term for traditional applications, “smart client”) deployment.
ClickOnce offers two modes of application installation: online only or full installation. For online-only applications, the application behaves much like a .NET application deployed through a HREF link today. The binary file is downloaded onto the local machine and stored in the Downloaded Program Files cache, but the user must be connected to the server that originally served the application for the application to run. In contrast, ClickOnce applications can be installed to run directly from a local drive. This installation mode resembles a traditional MSI install, with shortcuts added to the Windows Start menu and entries added to the Add or Remove Programs dialog.
To enable ClickOnce to work, a description of the files and assemblies that make up an application is required. In .NET 1.x, no real concept of an application exists. The dependencies of a particular assembly are recorded in its assembly manifest with no strong notion that a particular group of assemblies are part of a coherent group needed to execute an application. To address this need, .NET 2.0 and ClickOnce introduce the notion of an application manifest.
An application manifest is a standalone XML document that records the files and permissions that make up an application. The production of an application manifest is a development-time activity, and it is one of the tasks that IDE integration of ClickOnce made easier. Although IDE support would be nice, the .NET Framework SDK ships with the tools required to build this manifest file (even though given the file is XML, hardcore developers have the option of manually producing it). The next section covers how to use these tools.
The other file that is needed for a ClickOnce deployment is a deployment manifest. This file is more of a deployment-time task, and it would typically be created and updated by operations staff using the command-line or GUI tools in the .NET Framework SDK. A deployment manifest contains information about the most current version of an application available, the location of the application’s files and manifest, and the deployment mode and update policies. C# and Visual Basic .NET have IDE support for generating this file, but as with the application manifest, the file is relatively easy to produce with .NET Framework tools.
Deploying a C++/CLI Application Using ClickOnce
As a very simple example of deploying an application using ClickOnce, consider a C++/CLI Windows Forms application compiled with /clr:pure. This means that the application will use only MSIL instructions, but it may not be verifiably type safe (for those familiar with C#, it will be the equivalent of a C# application that uses unsafe features). To generate an application manifest file, the Manifest Generation and Editing Tool-Graphical Client (MageUI.exe), which ships as part of the .NET Framework SDK, can be used. This tool is a Windows Forms application that supports the creation, editing, and signing of both application manifests and deployment manifests.
The simplest way to launch MageUI is to start the Framework SDK command prompt (Start| All Programs | Microsoft .NET Framework SDK v2.0 | SDK Command Prompt) and simply type MageUI. On the first page of the tool, enter basic application information, as shown in Figure 1. In this case, the application is called COTest.exe.
Figure 1: Manifest Generation and Editing Tool-Graphical Client
The next step is to include a list of all the files that make up the application and locate the assembly that contains the application’s entry point. MageUI can do this automatically if all the files are placed in a single directory. This simple demo requires only a single file. Figure 2 shows the File page of MageUI.
Figure 2: Selecting the Files and Entry Point for an Application
The final step is nominating the security requirements that the application needs to run. For a C++/CLI application compiled with /clr:pure, the assembly produced will not be verifiably type safe, and the Full Trust permission set will be required. An application downloaded from an intranet or the Internet will not be granted this permission set by default. The end-user will be prompted to increase the permissions granted to this application when it runs.
Once the application manifest is complete, it can be signed and saved. The following are the contents of the manifest produced, excluding the XML signature, for COTest:
<?xml version="1.0" encoding="utf-8"?> <asmv1:assembly xsi:schema Location="urn:schemas-microsoft-com:asm.v1 assembly.adaptive.xsd" manifestVersion="1.0" xmlns_dsig="http://www.w3.org/2000/09/xmldsig#" xmlns_asmv1="urn:schemas-microsoft-com:asm.v1" xmlns_asmv2="urn:schemas-microsoft-com:asm.v2" xmlns_xsi="http://www.w3.org/2001/XMLSchema-instance"> <asmv1:assemblyIdentity name="COTest.exe" version="22.214.171.124" publicKeyToken="0000000000000000" language="neutral" processorArchitecture="msil" type="win32" /> <application /> <entryPoint> <assemblyIdentity name="COTest" version="126.96.36.199" language="neutral" processorArchitecture="x86" /> <commandLine file="COTest.exe" parameters="" /> </entryPoint> <trustInfo> <security> <applicationRequestMinimum> <PermissionSet class="System.Security.PermissionSet" version="1" Unrestricted="true" ID="Custom" SameSite="site" /> <defaultAssemblyRequest permissionSetReference="Custom" /> </applicationRequestMinimum> </security> </trustInfo> <dependency> <dependentAssembly dependencyType="install" allowDelayedBinding="true" codebase="COTest.exe" size="27648"> <assemblyIdentity name="COTest" version="188.8.131.52" language="neutral" processorArchitecture="x86" /> <hash> <dsig:Transforms> <dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms. Identity" /> </dsig:Transforms> <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /> <dsig:DigestValue> wWWjlZfzs0BZNXX3QyDQzJgRTTY=</dsig:DigestValue> </hash> </dependentAssembly> </dependency> <dependency> <dependentAssembly dependencyType="preRequisite" allowDelayedBinding="true"> <assemblyIdentity name="Microsoft.Windows.CommonLanguageRuntime" version="2.0.50215.0" /> </dependentAssembly> </dependency> </asmv1:assembly>
The final piece of the ClickOnce story is the deployment manifest. As with the application manifest, it can be produced by either the command-line or GUI SDK tool. To mix things up a little, this example uses the command-line Mage.exe. As stated earlier, a deployment manifest contains information about how an application is distributed and updated. To create the deployment manifest, use the following command line:
mage -New Deployment -ToFile CoTest.application -Name "CoTest" -Version 184.108.40.206 -AppManifest CoTest.exe.manifest
Looking at each of the command line parameters in turn, this statement will create a new deployment manifest to a file named CoTest.application. The name of the deployment will be CoTest, the most current version will be 220.127.116.11, and the deployment manifest will point to the application manifest CoTest.manifest. By default, the deployment manifest generated will run the deployed application in online-only mode (**The Visual Studio documentation in Beta 2 incorrectly states the opposite.**). To have the ClickOnce application installed so that it can be run offline, use the -Install true command-line parameter when generating the deployment manifest.
The following is the deployment manifest generated by the command line above:
<?xml version="1.0" encoding="utf-8"?> <asmv1:assembly xsi_schemaLocation="urn:schemas-microsoft-com:asm.v1 assembly.adaptive.xsd" manifestVersion="1.0" xmlns_dsig="http://www.w3.org/2000/09/xmldsig#" xmlns_asmv1="urn:schemas-microsoft-com:asm.v1" xmlns_asmv2="urn:schemas-microsoft-com:asm.v2" xmlns_xrml="urn:mpeg:mpeg21:2003:01-REL-R-NS" xmlns_xsi="http://www.w3.org/2001/XMLSchema-instance"> <assemblyIdentity name="CoTest.app" version="18.104.22.168" publicKeyToken="0000000000000000" language="neutral" processorArchitecture="msil" /> <description asmv2_publisher="." asmv2_product="CoTest" /> <deployment install="false" /> <dependency> <dependentAssembly dependencyType="install" allowDelayedBinding="true" codebase="CoTest.exe.manifest" size="1961"> <assemblyIdentity name="COTest.exe" version="22.214.171.124" publicKeyToken="63026ad33ba9ab1b" language="neutral" processorArchitecture="msil" type="win32" /> <hash> <dsig:Transforms> <dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms. Identity" /> </dsig:Transforms> <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /> <dsig:DigestValue> bBXpM0xYmqDcEqzUpD6Ja+F5XRU= </dsig:DigestValue> </hash> </dependentAssembly> </dependency> </asmv1:assembly>
The final step before placing all the files up on a Web server or file share is to sign the deployment manifest. Assuming the X509 certificate file is in the current directory, the following command-line statement can be used:
mage -Sign CoTest.application -CertFile cert.pfx -Password #4Ldd@otP -ti http://timestamp.verisign.com/scripts/timstamp.dll
The -ti command-line parameter specified the URI of the time-stamping service to use. This example used VeriSign’s service.
Once the signing is complete, the files are deployed to a file share or Web server (any Web server is fine—ClickOnce uses standard HTTP protocols and is not reliant on IIS or ASP.NET), and a link to the deployment manifest is sent out to users. Assuming they have the application prerequisites, such as the .NET Framework, the dialog that Figure 3 shows will be displayed when the user clicks on the link to the deployment manifest.
Figure 3: Validating the Application Requirements
If these checks pass, the user may be presented with a number of dialogs, such as when the application needs to be installed or that the Code Access Security permissions required by the application exceed those that would normally be granted to an application that originates from the Internet or an intranet. If the end-user agrees to these prompts, the application will be downloaded and begin executing.
Next month, the journey continues with a look at some of the other new features in the Visual C++ IDE.
About the Author
Nick Wienholt is an independent Windows and .NET consultant based in Sydney, Australia. He is the author of Maximizing .NET Performance from Apress, and specializes in system-level software architecture and development with a particular focus on performance, security, interoperability, and debugging. Nick can be reached at NickW@dotnetperformance.com.