This is a little follow-up from the VSTO workshop I did in Denmark on February 23rd and 24th. The two big questions I got of course where about deploying VSTO 2005 solutions:
Finally I have created a sample project demonstrating the capabilities of the Code Access Security object model to perform client side deployment and the capabilities of the ServerDocument for deployment on the server-side with updating deployment manifest locations in the documents.
WARNING:
For simplicity I have implemented all in Windows Forms applications which need to be launched manually. Of course all I did in the Windows Forms application usually needs to be done in an MSI installer package (you simply create a setup project with Visual Studio 2005 and then create a custom Installer class just by selecting "Add New Item" - "Installer Class" which then will contain the code I have just used in the Windows Forms application).
So rather think of these Windows Forms tools as MSI packages you create for your solution and one MSI package needs to be installed on the server and the other one needs to be installed on the client.
Server Side Deployment Package
To use the VSTO.ServerInstallTool you just publish the VSTO solution with Visual Studio 2005 to your local developer machine. Then you copy and paste the directory with the files created by the Visual Studio deployment wizard to the destination server in the destination directory and call my tool. The tool needs to be ran on the production server and wants you to enter the physical directory on the production server, the name of the virtual directory (only the relative name) and the file name of the application manifest (usually in the root directory of the published directory created by the Visual Studio 2005 publish wizard). Actually the tool does nothing else than iterating through the directory hiearchy and updating manifests for XLS and DOC files:
private
Client Side Deployment Package
On the client actually only the Code Access Security Policy needs to be setup. In environments with Active Directory I'd definitely recommend using Active Directory Group Policies for deploying these Code Access Security Policies and put them into the Enterprise Policy Level of Code Access Security configuration. For that purpose you can fire up the "Microsoft .NET Framework Configuration 2.0" in your Administrative Tools, move to the "Runtime Security Policy" node, rigth click it and select "Create Deployment Package". This creates an MSI that you then can deploy through Active Directory Group Policies across clients in your domain.
If no Active Directory is available, you need to provide your own MSI package. Actually using the package created the way above overwrites the complete configuration tree on the target machine. For single-machine installs or for "small" customers this is definitely not what you want. Therefore you must create a tool or MSI package that just creates (and when uninstalling, deletes) the nodes necessary for your single application (in this case VSTO application).
This is exactly what my VSTO.ClientInstallTool in this example is doing. It takes the strong name identifier of the VSTO customization assembly you have created and adds it based on this strong name as full trust assembly to your local configuration. Furthermore it adds a trust entry for the document's location (which is the URL to the server where the document has been deployed to).
The code leverages the Code Access Security Policy object model, as you can see:
private void CreatePolicyLevel(PolicyLevel pl, byte[] publicKey){ // Get the full trust permission set NamedPermissionSet FullTrustSet = null; foreach (NamedPermissionSet nsp in pl.NamedPermissionSets) { if (nsp.Name.Equals("FullTrust")) { FullTrustSet = nsp; break; } } if (FullTrustSet == null) throw new Exception("Unable to find FullTrust permission set!"); // Create the code group for the strong name assembly StrongNameMembershipCondition SNMembership = new StrongNameMembershipCondition( new StrongNamePublicKeyBlob(publicKey), null, null ); PolicyStatement PStmt = new PolicyStatement(FullTrustSet, PolicyStatementAttribute.Exclusive); UnionCodeGroup AssemblyCodeGroup = new UnionCodeGroup(SNMembership, PStmt); AssemblyCodeGroup.Name = "mszCool_" + Guid.NewGuid().ToString(); // Create the code group for the document url UrlMembershipCondition UrlMembership = new UrlMembershipCondition(ServerDocumentURL.Text); PolicyStatement DocPStmt = new PolicyStatement(FullTrustSet, PolicyStatementAttribute.Exclusive); UnionCodeGroup DocumentCodeGroup = new UnionCodeGroup(UrlMembership, DocPStmt); DocumentCodeGroup.Name = "mszCool_" + Guid.NewGuid().ToString(); // Add the code groups to the policy level pl.RootCodeGroup.AddChild(AssemblyCodeGroup); pl.RootCodeGroup.AddChild(DocumentCodeGroup); // Save the configuration SecurityManager.SavePolicyLevel(pl);}
Again, I'd really recommend putting this code into MSI packages which at the end is the exactly the same except that it is called from within an Installer class and that it either gets information from the user during setup or gets the information automatically within the build process of your application.
The ServerDocument actually can be used for another nice use case: it is a really good mechanism for updating deployment locations in existing documents of your users. Finally with the two object models introduced in this blog post, you are ready to got for deploying VSTO based solutions.
I have added the samples in the ZIP file in the ATTACHMENT OF THIS POST. So if you want to take a closer look at the code, just download, extract and go for it.