Editing Manifests

You can use several tools to edit deployment and application manifests.

Using MAGE to Edit Deployment Manifests

The Visual Studio Publish Wizard will automatically generate and update a deployment manifest for you, but should you want to edit the manifest yourself, you have two main options. First, the deployment manifest is nothing more than an XML file sitting on a server; you can use Notepad or any other editor of your choice.

If editing raw XML is not your idea of a good time, you can use the Manifest Generating and Editing tool, MAGE.EXE (see Figure 20-2). MAGE ships with Visual Studio, and provides a convenient graphical interface for editing deployment manifests. (Look in the SDKv2.0BIN directory of your Visual Studio installation.)

Figure 20-2. Using MAGE.EXE to manually update a deployment manifest to refer to a new version of the customization.

Unfortunately, the VSTO application manifest file format is sufficiently different from the ClickOnce file format that MAGE cannot be used to edit VSTO application manifests, only deployment manifests. To edit application manifests, you have a couple of options: You can use the VSTO Application Manifest Editor utility, or you can write your own tools using the ServerDocument object model.

Using the VSTO Application Manifest Editor

The VSTO SDK ships with a library of code samples, one of which is a graphical utility for editing application manifests. Load the ApplicationManifestEditor sample solution into Visual Studio and build it. You can then use this utility to edit the manifests inside of spreadsheets and documents (see Figure 20-3).

Figure 20-3. Using the VSTO Application Manifest Editor to edit the manifest embedded in a spreadsheet file.

Graphical utilities prove handy if you want to change a small number of files, but what if you want to make changes to many customizations at once? Then it would be nice to be able to write programs that edit the application manifests directly. Fortunately, the ServerDocument object model can manipulate not just the cached data inside a document, but also the application manifest.

Using the ServerDocument Object Model to Read and Edit Embedded Application Manifests

The ServerDocument object model, discussed in Chapter 18, was primarily designed to manipulate the cached data island on the server. However, you can also use it to read or edit the application manifest stored in a customized document. The ServerDocument object can edit the application manifests stored in Word documents saved in either binary or XML format, and Excel documents saved in binary format only.

We can modify our cached data viewer from Chapter 18 to display the application manifest inside a document.

Listing 20-3. Creating an Application Manifest Viewer with ServerDocument

using Microsoft.VisualStudio.Tools.Applications.Runtime; using System; using System.IO; using System.Text; namespace VSTOViewer { public class MainClass { public static void Main(string[] args) { if (args.Length != 1) { Console.WriteLine("Usage:"); Console.WriteLine(" AppInfoViewer.exe myfile.doc"); return; } string filename = args[0]; ServerDocument doc = null; try { doc = new ServerDocument(filename, false, FileAccess.Read); Console.WriteLine(" Application Manifest"); Console.WriteLine(doc.AppManifest.ToXml()); } catch (CannotLoadManifestException ex) { Console.WriteLine("Not a customized document:" + filename); Console.WriteLine(ex.Message); } catch (FileNotFoundException) { Console.WriteLine("File not found:" + filename); } catch (Exception ex) { Console.WriteLine("Unexpected Exception:" + filename); Console.WriteLine(ex.ToString()); } finally { if (doc != null) doc.Close(); } } } }

This section covers all the application-manifest-related properties and methods in the server document object model, describing what they do, their purpose, and why they look the way they do.

As mentioned in Chapter 18, because this object model enables you to modify all the information about the customization, it is quite possible to create documents with nonsensical deployment information. The VSTO runtime engine does attempt to detect malformed customization information and throw the appropriate exceptions; but still, exercise caution when using this object model.

 

Application Manifest Objects, Methods, and Properties

The ServerDocument represents the application manifest as an object of type AppManifest:

AppManifest AppManifest { get; }

The AppManifest object has no public constructors; the only way to get an instance of an AppManifest is by opening a ServerDocument object. However, after you have one, there is an easy way to turn an XML manifest into the programmable object model:

void Clear() void FromXml(string manifest) string ToXml()

The ToXml method turns the current state of the object model into XML. The Clear method throws away all the information in the manifest, making it a blank slate. The FromXml method clears the present state of the document before loading the information from the passed-in XML string. The AppManifest object also has four properties:

string DeployManifestPath { get; set; } EntryPointCollection EntryPoints { get; } Dependency Dependency { get; } AssemblyIdentity Identity { get; set; }

The AssemblyIdentity property is the "assembly" identity of the manifest, not of the customization assembly. This contains the application manifest's version number. If a deployment manifest is used, the VSTO runtime compares the application manifest and deployment manifest versions to see whether the application manifest is out-of-date.

The DeployManifestPath property gives the URL to the deployment manifest. This property sets the codebase attribute of the second installFrom element in the application manifest.

Using a deployment manifest is optional; if no deployment manifest path is set, the VSTO runtime assumes that the embedded application manifest is always up- to-date.

An EntryPointCollection is a straightforward strongly typed collection class that extends CollectionBase with these methods:

EntryPoint Add(string className) int IndexOf(EntryPoint entryPoint) void Remove(EntryPoint entryPoint) EntryPoint this[int index] { get; } void CopyTo(EntryPoint[] entryPoints, int index) void Insert(int index, EntryPoint value) bool Contains(EntryPoint value)

Like the AppManifest, the EntryPointCollection and EntryPoint objects have no public constructors. Use the Add method on the EntryPointCollection if you want to create a new EntryPoint. An EntryPoint has only one public property. It should be the namespace-qualified name of the view class:

string ClassName { get; set; }

The Dependency object has two properties:

string AssemblyPath { get; set; } AssemblyIdentity AssemblyIdentity { get; set; }

To load the customization assembly, the runtime needs to know both the full name of the assembly and its location. The AssemblyPath corresponds to the codebase attribute of the first installFrom element in the application manifest. As mentioned previously, it may be either an absolute or relative URL. If absolute, the assembly is loaded from that location. If relative, the path is relative to the location of the deployment manifest's codebase, if there is one, or the document, if there is not.

The AssemblyIdentity object does have a public constructor, unlike every other object in the application manifest object model:

AssemblyIdentity(string name, FourPartVersion version, string publicKeyToken) string Name { get; set; } string PublicKeyToken { get; set; } FourPartVersion Version {get; set; }

The Name property gives the name of the assembly, not the name of the file containing it; it should not end in .DLL.

The PublicKeyToken property is part of the strong name. A full public key encoded as a string is a rather long and unwieldy string. The public key token is a much shorter statistically guaranteed-unique key that identifies the public key used to verify a strong-named assembly. (See Chapter 19 for more details on what a strong name is and what the key token is for.) You can use sn.exe T myassembly.dll to give the public key token of a strong-named assembly.

Finally, the FourPartVersion object is a value type that keeps track of "1.2.3.4"-formatted version numbers. It has the following properties and methods:

FourPartVersion(int major, int minor, int buildNumber, int revision) int Major { get; set; } int Minor{ get; set; } int BuildNumber{ get; set; } int Revision{ get; set; } static FourPartVersion Parse(string value) static FourPartVersion Empty

The FourPartVersion class also overrides all the comparison operators so that you can easily compare any two.

Категории