Suppose you are ready to roll out an expense reporting application using a customized Excel spreadsheet. You plan to put the application up on the http://accounting Web site. Users will download the spreadsheet to their local machines for editing, but the code will live up on the server.
As discussed in Chapter 19, ".NET Code Security," you need to ensure that users have policy that explicitly trusts the customization assembly. The policy should either explicitly trust the server, or the strong name of the assembly or, preferably, both. See the last section of Chapter 19 for tips on how to roll out security policy.
Deploying to a Server with the Publish Wizard
Choose Publish from the Build menu to start up the Publish Wizard and give the name of the intranet Web server or network share to which you want to publish the customization as shown in Figure 20-1.
Figure 20-1. The Visual Studio Publish Wizard.
Click Finish. It is as simple as that; Visual Studio will build the customization and copy the document and customization assembly to the server. As you will see later in this chapter, Visual Studio also creates a deployment manifest for you. We discuss what exactly deployment manifests are for shortly, but first, what if you do not have write access to the server?
Some Security Questions
A few security questions may have just come to mind. What if your security-conscious administrators have not granted you write access to the Web site? What if the delay-signed assemblies must be properly strong-named by a signing authority, or signed with a publisher certificate before they are deployed?
The Publish Wizard creates a local copy of the files that it deploys up to the network site before it deploys them, but unfortunately there is no way to get the Publish Wizard to skip attempting to copy them up to the site. However, it is possible to do this from the command line, using the MSBuild.EXE utility. The syntax is as follows:
MSBuild.exe /target:Publish /property:PublishUrl=
This produces the files that would be deployed and puts them in the following directory:
For example, the following would produce the files to be copied up to the Web server, but not actually copy them up there:
[View full width]
MSBuild.exe /target:Publish /property:PublishUrl=http://accounting/ ExpenseReport "c: MyProjectsExpenseReportExpenseReport.csproj"
Instead, they would be saved in the following:
After you have the files to be deployed on your local machine, you can get them strong-named by your signing authority, send them to the server administrator to be copied onto the Web server, or do whatever else needs to be done before the files become available on a live server.
Examining the Generated Files
Take a look at the contents of the network (or local) directory to which you just deployed the application. (This will typically be a subdirectory of the c:inetpubwwwroot directory if you published to a Web site.) You should see a directory structure that looks something like this:
> dir /s /b C:InetpubwwwrootExpenseReportExpenseReport.application C:InetpubwwwrootExpenseReportExpenseReport.doc C:InetpubwwwrootExpenseReportExpenseReport_188.8.131.52 C:InetpubwwwrootExpenseReportExpenseReport_184.108.40.206 ExpenseReport.dll C:InetpubwwwrootExpenseReportExpenseReport_220.127.116.11 ExpenseReport.dll. manifest C:InetpubwwwrootExpenseReportExpenseReport_18.104.22.168 ExpenseReport.doc C:InetpubwwwrootExpenseReportExpenseReport_22.214.171.124 ExpenseReport.dll. config
To understand what is going on here, we need to introduce some jargon. The ExpenseReport.application file is the "deployment manifest," and the Expense Report.dll.manifest file is the "application manifest."
It is somewhat confusing that the ".application" file is not the application manifest; unfortunately we are stuck now with this poor choice of nomenclature.
The Deployment Manifest
The sole purpose of the deployment manifest is to point the VSTO runtime toward the most current version of the application manifest. The application manifest by contrast contains information about where the customization assembly is and which host item classes need to be created when the customization is started. There is always only one deployment manifest, but there can be many application manifests, one for each version of the customization.
A typical automatically generated deployment manifest looks something like this.
Listing 20-1. The Deployment Manifest
We have emphasized the relevant portions of the deployment manifest. What is all of the rest of this stuff? There seems to be some confusing things in here. Why is the root element "assembly"? Why are there two inconsistent "assemblyIdentity" elements? And what's that digital signature?
VSTO uses the same deployment manifest format as "ClickOnce," a technology designed to facilitate deployment of entire applications, not single customizations; these oddities are a result of backward-compatibility factors from the ClickOnce world.
The oldest of these historical factors is the root element "assembly." Explaining that strange choice requires us to go back to a time before the version 1.0 .NET runtime shipped. When the .NET runtime was being designed, "assembly" referred to all of an application's files and configuration information. That is, all the bits described by what we now call a "manifest." The manifest file format above dates from that time, and its elements were not renamed when "assembly" came to mean "the smallest unit of versionable executable code."
That then explains why there are two inconsistent assemblyIdentity elements. The first assemblyIdentity identifies not a DLL but rather the manifest itself. Notice that the first assemblyIdentity element names the manifest. Manifests can have their own version numbers. Deployment manifests are usually versioned along with the customization assembly, but the deployment manifest can have its own version number distinct from that of the customization assembly if you so choose; as you will see later, it must be consistent with the application manifest, but need not be consistent with the customization assembly. VSTO considers only the name and version attributes in the first assemblyIdentity element.
The second assemblyIdentity element uses "assembly" in the modern sense, and identifies the customization code. Notice that the codebase attribute gives the relative path to the application manifest, and the assemblyIdentity identifies the name and version of the customization code. We discuss the meanings and interactions of the various codebase attributes later in this chapter.
Finally, ClickOnce supports digital signing security features in its manifests; unlike ClickOnce, VSTO does not do any kind of digital signature verification on its manifests. VSTO will ignore these elements.
The Application Manifest
As you have seen, the deployment manifest identifies the location and current version of the application manifest. The application manifest identifies the customization assembly and lists the classes that need to be created when the customization starts up. The application manifest looks somewhat similar to the deployment manifest.
Listing 20-2. The Application Manifest
Again, we have "assembly" used in the now-obsolete sense as the root element and an assemblyIdentity element that gives the version number of the application manifest. What is all the rest of the stuff in here?
Clearly, all the information we need to start up the customization is in here, but again the format is somewhat odd because it tries to be similar to the ClickOnce format. We have a collection of entryPoints listing the classes that are to be created when the customization starts up. We also have a single "dependency" (that is, the assembly containing the customization). Because a ClickOnce application manifest describes all the assemblies that make up an application, a ClickOnce manifest can have many dependent assemblies; a VSTO customization always consists of a single assembly, and therefore has only one dependency in the application manifest.
Notice that the application manifest also refers to the location of the deployment manifest. But is not the point of the deployment manifest to identify the location of the application manifest? What is going on here?
The Relationship Between Application and Deployment Manifests
The easiest way to explain this is to walk through a typical deployment scenario. Suppose you develop and publish version 126.96.36.199 of the expense reporting solution above. There are now four interesting files: the deployment manifest, the application manifest, the assembly, and the document. The deployment manifest points to the application manifest, the application manifest points to the assembly, and the document's data island contains a copy of the application manifest.
Now you e-mail the document, without the assembly, to a user. The user loads the document into Excel. The VSTO runtime reads the copy of the application manifest out of the document and notices a deployment manifest in the "installFrom" location. The VSTO runtime downloads the deployment manifest and discovers that both the application and deployment manifests are version 188.8.131.52. Therefore, the VSTO runtime knows that the document contains the most recent copy of the application manifest, and need not update it.
The deployment manifest's codebase refers to the location of the server's copy of the manifest and the customization DLL. The CLR assembly loader then downloads the assembly and configuration file, caches them locally, and loads the assembly into memory. (Although the file has been cached locally for convenience, the CLR assembly loader sets the evidence associated with the assembly to match its original location, not its temporary location on the local disk.) The VSTO runtime then starts up the classes named in the entryPoint elements, and the customization runs.
A few days later, you fix some bugs and roll out version 184.108.40.206 to the server using the Publish Wizard. The next time that the user starts the document while online, the VSTO runtime contacts the server to see whether there have been any changes in the deployment manifest.
This time the document's copy of the application manifest is 220.127.116.11, but the deployment manifest is 18.104.22.168. The VSTO runtime downloads the new application manifest from the server and caches a copy of it in the document. (Note that if the user quits Excel without saving the document, the change to the cached manifest will be lost with all of the other changes.)
The CLR loader detects that the assembly's codebase is different and downloads the new assembly. The user is now running the latest version without ever having to download or install anything manually.
Because the local copy of the application manifest knows where the deployment manifest is, and the deployment manifest knows where the latest application manifest is, the document can keep itself always up to date with the latest bits.
A deployment manifest's version number must match the version number of the application manifest it refers to. If the deployment manifest's version attribute indicates that it is version 22.214.171.124, the referred-to application manifest must also be version 1.0.01. If the VSTO runtime detects that the deployment manifest refers to a mismatched application manifest, it assumes that the deployment server has been corrupted and refuses to load the customization.
Determining the Assembly Location from a Deployment Manifest
Did you notice that between the deployment manifest and the application manifest there were three codebase attributes? The application manifest says this:
Whereas the deployment manifest says this:
How does the loader actually determine the codebase from which to load the customization assembly? In the preceding example, the application manifest has an absolute path to the deployment manifest, so the runtime starts there. The absolute path to the deployment manifest is combined with the codebase in the application manifest which is relative to the deployment manifest path for a published project. So the VSTO runtime looks for the assembly in http://accounting/ExpenseReport/ExpenseReport_126.96.36.199/
Had the application manifest contained an absolute path to the DLL, the VSTO runtime would ignore the deployment manifest information for the purposes of loading the customization, and just use the absolute path. You learn how to edit the codebase and other attributes in the application and deployment manifests later in this chapter.