Skip navigation

Author: Jeff Noble

This article is available as a pdf here: Signing and Deploying CAB Based Click Once Code

Overview

This document will describe the steps needed to build and deploy a Composite UI Application (CAB) based software package using Click-Once technology. This document will describe the process as it applies to c# applications. While the process is similar in VB.net, I will leave it up to you to convert where applicable.

Prerequisites
To use this document you should have the following steps completed.
A project build using CAB (written in c#) should be free of build errors.
Have access to the ManifestManagerUtility.exe which can be found in the Click Once Community Resource Kit here: http://www.codeplex.com/smartclient/Project/FileDownload.aspx?DownloadId=5060

Have access to a Certificate Authority whose root certificate is trusted on the domain.
Have access to a test client system. A virtual machine is fine for this as long as the operating system is the same as the majority of your users. You can also use your development machine if you don’t have an extra PC, but the effects are more explanatory if you actually use at least VirtualPC or VMWare (both are free).

Preparing the Application
Applications built using CAB do not contain references to their modules. While this plays well into the loosely coupled architecture of CAB, it does not support the Click Once notion that all files needed are referenced by the project. To combat this we will first let Click Once do its thing as far as publishing and signing goes. After that we will make some changes, and then be ready for the actual deployment.
Since we will be letting Visual Studio publish, and then we will modify the published information, it makes sense to publish to somewhere that is not public. That way we can stage the publish, make our changes and then copy the completed publish to a live location. This will prevent a user from getting the changes pushed before we are able to make our needed changes.To make things more entertaining I am going to describe a scenario where we want more than one version available of our application. We will prepare a production release and a development release. Each will live in its own deployment directory (dev and prod) and will be maintained separately. The applications will be available offline as well as online. Meaning that if the network goes down the application can still launch. It will be up to you to provide for this in your application, but suffice it to say that we will allow for simple offline data collection.

Turn On Click Once
The first step is to tell Click Once of the permissions you will need for this application. This is no easy decision as there are many factors that go into each item. For the purposes of this document, we will be creating a full trust application. This means that our application will have access to write to the registry, the hard drive, have network access, etc. While we could restrict the application to only allow the items it needs, doing so would make this document extremely large, so we will keep it simple.
Setting the Trust Level
Right click the Properties folder in the shell project and select Open. Then click the Security Tab. 
Trust Level ImagePut a check in the ‘Enable ClickOnce Security Settings’ check box. Also, select ‘This is a full trust application’. This tells a client computer that the program will want to do all kind of fun things to the clients computer. The computer in response will let the user know of the danger. We will later be signing this code and setting up a trust so that the client computer trusts our code and doesn’t bother the user.

Setting the Publish Point

The next thing we need to do it setup a publish point. We can do this with a file share, an IIS virtual on a web server, an FTP, etc. For the purposes of this document we are going to use a file share. If you would like to use IIS because you want to hook the http headers and do silly things like that, you can just change the UNC path that we will use with an http path.

It is important to remember that our publish point is private so that we can make changes to the deployment before issuing it for public consumption. With that in mind, lets create a couple of directories. Using the famous Noble Nomenclature (sometimes called Nobleclature, or lazyclature), I will create two directories as follows:
c:\1Deploy_DEV
c:\1Deploy_PROD
The 1 makes these stay at the top of the folder listing and also makes you think of yourself as number 1 when you type it .

The next step is to create shares for these. This is where the UNC path stuff comes into play. I will right click and share these folders as file://machinename/DeployDEV and file://machinename/DeployPROD.

Now that we have our publish points created, it’s time to tell Visual Studio and Click Once about the drop locations. We will be working on creating a Click Once deploy for production first.

Right click the Properties folder in your shell project and select Open. Then select the Publish tab. 

 Image 4

 Type in your UNC path into the Publishing Location and then select ‘The application is available offline as well (launchable from the Start menu)’. I am selecting this instead of online only, because my application will allow people to use it in an offline mode. I also don’t like to tie all of my users to a network resource. Lets say I used a Publish location of http://myintranet/myapplication/hello.application. If the web server that hosted this resource were to go down, nobody would be able to launch my application. Remember that my network is up and running, it’s just that one box that went down (not that IIS EVER has trouble). For this reason, I use unc paths. I can have my installation files hosted on a box that is mission critical. If that box goes down, my application is probably un-useable anyway. In addition to this, I like to allow for launching even if the network is down. I can collect data in an offline mode, and then batch import it when the network comes back. This makes me happy, and this is what I shall do .

Your version will start out at 1.0.0.0 and will increment automatically (as long as the checkbox is checked) with each publish. Notice that mine shows I have published 4 times already and am ready for publish 1.0.0.5.

Checking and Fixing Application Files
Next we move on to the Application Files Button. Clicking it will reveal a couple of problems for CAB.

The First problem is the ProfileCatalog.xml file. This file gets incorrectly marked as a data file. As such it won’t be available to CAB after it deploys. Make sure you change the publish status to ‘Include’ for this file. I changed all of them to include, but I really am not sure what the effect of this is as opposed to Include (Auto). I just don’t trust most things that claim to be automatic. Look at Martin Gramatica, he used to be called Mr. Automatica and look what happened to him.

Image 6

The next thing to notice is that in the list of applications, you don’t see ANY of your CAB modules you worked so hard on. This is because Click Once only see’s the output files in the project and the project references. This will not work for us. We will go ahead and leave it this way for now. We will even publish it this way, but then we will add the missing files (more on that later).

Changing Our Options
After clicking OK we need to click on the Options Button. In this dialog we need to change the Publisher name and Product name. The product name is the name that will be displayed on the start menu after this application deploys. It does not however tell click once that this is a different installation. In other words, just changing the Product name here and re-deploying will not result in two start menu icons. The start menu WILL use this name, but ClickOnce will still treat these builds as if they are the same. Deploying the second time will overwrite the existing start menu item. We will cover how to avoid this later. I just wanted to point out that this is the name that goes on the start menu and nothing more.

Image 8

I also unchecked the Open deployment web page after publish. I don’t like being spammed by browser windows from Visual Studio.

A Word on Developing
While you develop I recommend using a test certificate. You can even install the certificate as a trusted publisher if you like. This will allow you to work on the project without knowing the real certificates password. Once you are ready to deploy then you can create the real certificate and deploy in a trusted manner.
Signing the Manifest?
Ok, here is where the really confusing stuff happens. This is going to get really really hard. Did I scare you? Oh well. This stuff is actually quite simple, but it is a lot to go through. I do promise you that once you go through this a couple times, you will be able to do everything in this document in a matter of minutes. It just takes a lot to explain it in detail. I will do my best. The following is an explanation of how the digital signing works and why we need it. Once you understand that, then I’ll go through how to do all the wacky junk we just explained. So …. On with the junk.

Certificates
Most of the articles you will read talk about getting a certificate from a trusted authority (like Verisign, or Thawte). If you are planning to deploy your application in your intranet (like I am) and your remote users will have access to your local network (your remote users VPN into the corporate network) like mine do. Then you really do not need to purchase your certificates. What you will need is a Certificate Authority (CA) installed within your domain. You will also need to run the CA on Windows Server 2003 Enterprise edition. Without Enterprise edition you will not be able to make the needed templates for use with ClickOnce. I installed my CA in a VMWare virtual machine but you can use a spare box (I just didn’t have one readily available). Installing a CA is outside the scope of this article, but I will give you an abbreviated version that worked for me. Make sure you check with your Administrator to see if this is the correct setup on your network. Ok, I warned you! You get to the CA installation from the Add Remove Programs and click the Add Remove Windows Components button on Windows Server 2003 Enterprise Edition.

Creating your own CA

IMage 10
We already had a CA on our network so I made this a subordinate CA. Your administrator will have to make sure that your CA is trusted as a Root
Image 12

Creating a template that works!
Then you can create a new template for the CA.
Image 14

Some names have been hidden to protect the innocent. As you can see from the above, the CA already has a Code Signing template (you may have to add it manually to the list of available templates). The problem with this one is that the private key is marked as not exportable. We will need the private key information to create one of the files we need for ClickOnce. There is no way to edit the Code Signing template. However, you can create a copy of it and change whatever you need on the copy. Then you can use that new copy to create what we need. To do all this mumbo jumbo you will need the Certificate Templates snap-in.

Here is a look at the existing code signing template (ignore the one I blocked out, it was requested by my employer).
Image 16
Notice that some of the icons are grayed out. This is because they are not editable. We can only edit the new type of certificates that we make. So to do that, just right click the Code Signing template and duplicate it.

Image 18

This is where we can change the things we need. Duplicating the template opens up the Properties of a new template dialog box. The first thing to do is change the name and how long the certificate will be valid.
Image 20

Then click the Request Handling tab. This is where we tell the template to allow exporting of the private key.
Image 22

Then just click ok to add the template.

What we just did was created a certificate template. That means that once we add this template to our server, you will be able to request a certificate based on this template. This certificate will then be applied to our manifest, digitally signing it to prevent tampering. So next we add the certificate to the CA.
 

Adding our new certificate to the CA
All we have to do is right click our Certificate Templates folder in our CA (not in the Certificate Templates snap-in, this time it’s back in the actual CA snap-in in the templates folder). Select Certificate Template to Issue.
Image 24

In the list provided, select the template that you just created.
Image 26

Now restart your CA service and you are ready to use the new certificate!
Image 28

Certificate Files

What the heck is a .cer and a pfx file?
A .cer file is a certificate file. It may or may not contain an exportable private key (ours will). The pfx file is a private key file we can use in ClickOnce to sign our manifest. While there is a TON more to tell about certificate files, I want to keep it simple. People seem to get overwhelmed, so I am going to keep it very simple. You only need to know that we are going to sign our manifest with the .pfx, and we are going to use the public key out of our .cer to make our clients trust us as publishers.

What is a publisher and who is the root?
One of the most common questions I get is, “I don’t understand the whole root and publisher thing, can you explain it?” In a nutshell, there are three players involved in a trust situation. Imagine that I am your friend. You trust me implicitly. If I give you some software and tell you that it is safe to install, then you would trust me (hopefully). However, if you just met somebody in a back alley and they told you to install some software would you trust it? How about if that same person told you they signed it, would you trust it then? The answer should be a resounding NO! You don’t know that person and you cannot trust that just because they say it’s ok that it really is. Even though they signed it, who are they to you? Get it? Now if they gave me the software and I told you yes it’s ok to use, then you once again could trust it.

This is exactly how all this stuff works. The thing that gets confusing is when you are the CA, the developer and the client (when you test the application). To keep things straight, as you do each step you should imagine yourself working for some other department. The CA is the one you trust. Your Administrator in your environment has configured your network and all of the computers on it to trust the CA. This certificate should be visible in the Trusted Root Certificate Authorities folder in your local client machines certificates snap-in. If it isn’t talk to your admin and make sure it gets propagated. If you installed a subordinate CA your users will only need to trust the main CA as long as everything is configured correctly.

Notice in the Trusted Root Certificate Authorities folder is certificates for Verisign and other trusted root certificates.
Image 30

These are your friends in the explanation above. If any root certificates in this list say software is safe to install, then your computer will trust them. Now, we are a trusted root as well (well at least the CA is).

What happens if we are not trusted?
We do have the ability to sign our manifest with our Code Signing template that we created and deploy the files using ClickOnce. The problem is, that if we are not a Trusted Publisher, the end user will be prompted with a warning:
Image 32

While this dialog box would normally be ignored by most users, it really should never be seen. If I want to deploy software within my company, I should be trusted on the network and on the client machines. We are going though this portion of the document, to get rid of this warning dialog box. Plus it’s really cool to see this work as advertised!!

The next thing we want to do is to make ourselves a trusted publisher. That is, we want to tell our computer, that some developer is trusted by some root certificate (our CA). We are now the back alley guy who is looking for a trusted friend to tell everyone on our network that we can be trusted. In Certificates snap-in under Computer, you can see a folder called Trusted Publishers. We (as developers) need to be in that folder for windows to trust our install and not warn us. This is as easy as putting the certificate into the folder, but who is going to do that? For the sake of keeping it simple, we will do that part manually for this portion of the article. At the end of this article however, I will describe how to push this trust out via Group Policy and make this a seamless hands off operation (with the help of an Administrator friend).

Generating a Certificate
Now to make sense of all that setup we just created. Time to create a few files. Open up internet explorer and go to your CA. It should be at http://yourCAserver/certsrv/.
Image 34

Click Request a Certificate.
Then click Advanced Certificate Request.
Image 36

Next click Create and submit a request to this CA.
Image 38

Select the certificate template we created earlier. Make sure the Mark keys as exportable is selected.
Image 40

Click the submit button.
You should then see this page:
Image 42
***If you do not see this page, you may have a CA setup to manually issue certificates, all you have to do it go into the snap-in for the CA and right click the certificate in the pending folder, and issue the request. Then go back to the website, and check the status of an existing request. You will find the certificate waiting for you.

Click the Install this certificate link.
Your certificate is now installed in your personal certificate store.

We need to get two files from this certificate, a .cer and a .pfx. First for the pfx.

Exporting the private key
Open the certificates snap-in for the current user.
Image 44
In the right hand pane right click the certificate you just installed and select Export. The following wizard will display:
Image 46
Click Next.

We want to export the private key as we will need this later.
Image 48
Click Next.

Leave everything the same for the export file format page of the wizard.
Image 50

Click Next
Type and confirm a password for the private key in the next page of the wizard.
Image 52

Click Next.

Give a path for the location of the saved private key file.
Image 54

Click Next.

Image 56

Click Finish. The private key file is now in the specified path.

Exporting the public key
This process is the same as the private key. I will display the exceptions here, but just follow the Export private key instructions for the most part.

On the Export Private Key page of the wizard, choose No.
Image 58

On the export file format page of the wizard, select either DER, or Base-64 options as they will give us a file with the .cer extension.
Image 60

Save the file with a .cer extension.

You now have the two files you need. Although it is a lot to document, once you understand what you are doing, and have the needed items installed in the CA, you can request a certificate and extract the needed keys in a minute or two.

After all that, what do I do with these stupid files?
Whew, that was a lot to explain, but hopefully you are with me. Here is a quick re-cap of what we have accomplished this far. We setup our code for ClickOnce (more of that is needed now); we installed our CA which is a one time thing. We created a reusable template for creating a Code Signing certificate with an exportable private key (.pfx file). Lastly, we exported the public and private keys from our installed certificate in our store.

The next thing we need to do is to setup our Trusted Publisher on our client machine. Remember this is where we switch hats. We are now acting as the end user (client). Copy the .cer file to the client machine. In the client (I am using a VMWare virtual machine; you can use your workstation if you need to), open the Certificate store for the computer (snap-in). Right click the Trusted Publisher folder. Choose All Tasks -> Import.
Image 62
In the wizard, navigate to the .cer file and finish out the wizard with no other changes. What we just did, was told the client computer that any software pushed by the publisher described in the certificate should be trusted. The certificate is signed by a trusted root because the CA that signed the certificate is already trusted (we made sure of that before).

To see the certificate, you can double click the certificate (either the .cer file, or the entry in the certificate store). It will show you the details:
Image 64

Great! Now we are trusted.

Sign and Deploy
Signing and CAB
We are about to sign the manifest with our certificate. The problem is that since we are using CAB, the shell project does not contain our smart parts or any other references for that matter. When deploying a ClickOnce application the ClickOnce output generated by Visual Studio includes the files and references in the project being signed and deployed. This means that in a CAB environment you either have to reference your modules in the shell, or modify the manifest and re-sign it when you are done. I prefer not to add the references because one of the benefits of using CAB is that it’s loosely coupled and I want to preserve that. You can make your own decision. Adding the references is only for the purpose of telling Visual Studio that you want to include the dlls in your bin directory and that you want ClickOnce to include the files in your manifest. Again, we will do it all manually.

Deploying the Shell
Let’s go ahead and deploy the shell. This will not include any modules. We will add those later. In the shell project, select the Signing tab in the project properties. In the following diagram, I have a test certificate installed. We will be replacing this with our Code Signing certificate.
Image 66
Assigning the Code Signing Certificate
Click on the Select from File button. Navigate to your .pfx file. When prompted, enter the private key password.
Image 68

After clicking Ok, you should see your Code Signing certificates information in the certificate area.
Image 70

Finally Deploy the application
Ok, now build your project and then to deploy it, either select the Publish tab, or choose Publish
on the Build menu. This will bring up a wizard. After the first time, you can just click finish right away, but we will go through it here so that you understand the steps.

Image 72

This is the location from the publish tab itself, it’s just giving you one last chance to change your mind. I am using a file share here, but notice that you have examples of other types of deployment options.

Click Next.

Image 74
Leave the default and click next.

Image 76

The main difference is the shortcut on the start menu. This works well for me. You can choose which ever one you want. Again, this is copied from the Publish tab.

Image 78

Ok, here we go!! Click Finish.

Your project will build and then publish to the deployment folder.

Errors
If you get any errors like the following:
Could not find a part of the path ‘C:\…\bin\Debug\Shell.publish\Shell_x_x_x_x’.
The easiest way to move on is to just bump the revision number up on the Publish tab and republish.

Test the Deploy
Now we are going to install the application, remember that this is just the shell. Go to your client (end user) environment (my VMWare machine). Navigate to the share (Start -> Run).

Image 78

In the window that opens you will see something similar to the following:

Image 82
Double click the Shell.application file. This will launch the click once install. First you will see the application check the manifest on the server and determine if it needs to install anything locally.

Image 84

For us this is the first time, so it will download the program and run it. Hopefully all goes well up to now. If you notice (or didn’t notice) it did not ask you to ok the publisher. We are all trusted now!

Errors
If you see errors, you will want to do a couple things:
Run the exe in the bin directory. Make sure this an actual ClickOnce problem and not a bug in your executable.
Look in the deployment directory (C:\1DeployPROD\Shell_1_0_0_4). Compare the files to those in your bin directory. All of the files in the folder will have a .deploy extension, but the files are unchanged (you could remove the .deploy extensions to test the .exe).
If files are missing, which is likely when using CAB, then you’ve found the reason for the error. You can either add the files in the publish tab (application files button). Or you can add them manually when we add the modules and their dependencies. The important thing to realize is that the application did deploy and did try to run (albeit with errors). The ClickOnce and signing portion really did work.

Adding the Missing Files
Whether you had errors running, or just didn’t see your modules from CAB you will need to add the missing files. The steps are simple. Just modify the manifest to add the missing files, and then re-sign the manifest with our certificate.

There are a couple different ways to add files to the manifest. You can use the tool that comes with .net called Mage. It has flavors for command-line and GUI. Mine is installed in C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin. Using this tool has a couple limitations, and I have stumbled upon a better tool.

Tools to Manipulate the Manifest
If you want to know more about the options check out the ClickOnce Community Resource Kit. It was put together by Brian Noyes. He is an authority on this stuff (he even wrote the ClickOnce whitepaper for Microsoft). Get the ClickOnce Community Resource Kit here:  http://www.codeplex.com/smartclient/Project/FileDownload.aspx?DownloadId=5060

In that kit there is GREAT pdf showing you how to do all kind of things with both Mage and his tool (which comes with the Resource Kit). My examples will use Brian’s tool called Manifest Manager Utility.

To continue, please download and compile the Manifest Manager Utility.

Fire the Manifest Manager Up
Before you start, you need to find all of the files you need to deploy. I would suggest a manual run, because many of the problems I have had with CAB deal not with ClickOnce, but with missing files. Create a directory and copy all of the files in the shell bin folder to this new directory, then copy the module dlls and referenced files from their bin folders to this new directory. When all of the needed references and files are in there, run the shell.exe from the firectory and test your application. If it doesn’t work in there, it won’t work when deployed via ClickOnce. Ok, you’ve been warned!!

We will go through two different iterations to keep things clear. The first example will simply add the files we need to the manifest and sign it. The second example will give us the ability to run side-by-side versions of the same ClickOnce deployed application.

Adding Missing Files
Run the Manifest Manager Utility. You will see the following screen:

Image 86

Click Open.

In the Open File dialog box, choose the deployment manifest file. This is the file that has a .application extension, it is in the root deployment folder and does NOT contain the version in the name. For my example it looks like this:

Image 88

Click Open.

You will now see the files contained in your manifest. All we have to do is click the add button:

image090.jpg

When using CAB, all of your files should be in the projects bin folder (especially if you used the Guidance package to create your projects (I do). If not, don’t worry, you will just have to get your files from many locations (each modules bin folder).

Finally Adding the Files
I will navigate to my bin folder and select the missing files.

image092.jpg

I can’t forget CSLA (thanks Rocky)!!Don’t forget this one if you use Enterprise Library:

image0921.jpg

Click Ok.

Next you are provided with a destination location dialog:

image094.jpg

Select the location where you want these newly added files to live. I prefer to keep them with the other files already in the manifest for the version that I am about to push, so I will put them here:

image096.jpg
Click Ok.

Now the list of files should match the manual run test you did earlier. If everything is ok, then all we need to do is save and sign the manifest. So just click the Save button. You will see the following dialog:

image098.jpg
Point the path to your .pfx file that we created so long ago.
Type the password for the .pfx file.
Click Save and Sign.

That’s it!

Testing It All Out
Go to your client machine environment and run the application from your share. Mine looks like this:
file://jnoble/DeployPROD/Shell.application

You should see:

Image 84

Then this:

image100.jpg

(If you saw a dialog asking you anything, then your certificate is not trusted).

Then the application should run.

Viola!

Side by Side Execution
Earlier I spoke of running different version side-by-side. What I mean by this is I want a development version (beta) and a production version (RTM) installed on my machine. If we don’t do anything and just deploy two versions to two different folders, the client will assume that they are the same version and overwrite the last one each time you run. This is bad, especially if you want icons on the start menu for each of them (offline mode of ClickOnce).

Telling ClickOnce They Are Different
Remember back in the Setting a Publishing Point section of this document that we setup two deploy folders? Our folders were for production and development. We have only been using production up until now. We will leave the production one alone since we already have it deploying via ClickOnce and it’s good to go. What we really have to do it tell ClickOnce to treat our development version as if it’s a totally separate application. Here is how we do this:

Set the deployment location.
Set the name to development in ClickOnce.
Rename the manifest file.
Change the Application Identity in the deployment manifest.
Change the Deployment Provider in the deployment manifest.

Sounds tricky huh? Well it isn’t. As a matter of fact only two changes are in Visual Studio. The rest is in the Manifest Manager Utility.

So, go back to the shell and open the Publish page of the project properties.
Step 1: Set the deployment location to our development share.

image102.jpg

Step 2: Click the Options Button. Change the product name to show a new name. This is the name that will show up on the Start Menu.

image104.jpg

Click Ok.

Build the application.

Publish the application.

Step 3: In Windows Explorer rename the manifest file to a unique name, but remember the name. I used this:

image106.jpg

Now fire up the Manifest Manager and open your new manifest. (Shell-DEV.application in my case).

Step 4 & 5: Change the name in the Application Identity and the Deployment Provider.

image108.jpg

Now just add the missing files and sign and save the manifest (shown in the previous example labeled Finally Adding the Files).

New Install

Background
Ok, so we know what to do and are all set, but how are we going to push out this trusted publisher to the machines on our network? While I am sure that there are many creative ways to do this. I came up with one that works for me. I hope it works out well for you too.

All I really wanted to do was to install my trusted certificate in a client machine. Later I would add a desktop icon to the desktop, but I’ll leave that for another blog article. I decided to have a friend create a group policy in Active Directory and that we would push an installer.msi onto the client machines on our network. All I had to do was create an installer that would install our certificate (.cer file) into the trusted publishers store on the client machines and the group policy would push the software to the client and run the installer. Perfect! But how do we do that…. After much research (and trial and error). We came up with the following:

Creating the Installer
In Visual Studio add a new Setup Project (under Other Project Types, Setup and Deployment).

image110.jpg

Setup the Setup
Now we have to add the certificate file to the installer.

image112.jpg

Select your .cer file in the Add Files dialog.

We will place the .cer file in the System32 folder on the clients machine because I don’t want them to mess with it and most people don’t even look in there. If they do find it, it’s fine because it’s just a public key file. You can’t sign with it.

Adding the System Folder
We have to add the System folder to our installer. Double click your .cer file in the project and then right click the File System on Target Machine icon.

image114.jpg

Now select the Application Folder and drag the certificate icon from the Application folder to the System Folder:

image116.jpg
So that takes care of deploying the certificate to the client. Now all we have to do is have the installer put it in the trusted publishers store.

Trusted Publishers Installer Class
Add an installer class to your project

image118.jpg

Now delete the class1.cs and add an installer class to the project.

Next add a committed event to the class. This will get called by the installer when it enters the commit phase of installation:

image120.png

Add the following code to the Committed event handler:

using System.Security.Cryptography.X509Certificates;
private void ApplicationInstallerHelper_Committed(object sender, InstallEventArgs e)
{
 X509Certificate2 certificate = new X509Certificate2(Environment.GetFolderPath(Environment.SpecialFolder.System) + @"\MyCompanyApplication.cer");
 X509Store trustedPublisherStore = new X509Store(StoreName.TrustedPublisher, StoreLocation.LocalMachine);
 try
 {
   trustedPublisherStore.Open(OpenFlags.ReadWrite);
   trustedPublisherStore.Add(certificate);
 }
 catch (InstallException ex)
 {
   // write to eventlog here.
 }
 finally
 {
   trustedPublisherStore.Close();
 }

This code creates a new certificate object and loads our certificate from the file. I use the Environment.GetFolderPath() function to get the actual path of the system32 folder on the client machine.

Next I create a Certificate Store object and set it to the Trusted Publisher and Local Machine (as opposed to the user scope). This will install in the proper place for trusted publishers on the client machine.
Finally I just open the store, add the certificate and close the store.

Installer Meet Installer Class
We have all that we need to work except there is no communication setup between the installer class and the installer. To make this work it takes two steps.
Add the installer class output to the installer project.

image123.jpg
Add custom events to the installer project so that each phase of the install will notify our installer class. (We have code in the committed event that our class will react to).

First add the installer class output to the installer project.

Select the installer class:

image1251.jpg
Make sure primary output is selected.

Next right click the application installer project and select Custom Actions from the View menu.

image127.jpg

Now right click each folder in the custom actions and add a Custom Action

image129.jpg
Select the Application Folder select the Primary output from your Installer Class and click Ok.

image131.jpg

Do this for each folder. You should be left with the following:

image133.jpg
*We only really care about the Commit Action, but I like to add these because if I ever need to react to different events in my installer class, it’s all hooked up for me.

That’s it!

Test it out
Now compile the Application installer and you can run the .msi file it creates on your client to automatically install the certificate in the Trusted Publisher store.

Once you verify that it works (just check the snap-in to see your certificate in the Computer Store’s Trusted Publisher folder). Then we can give the installer to the group policy. The group policy will then push this out and run it for us.

Ty-ing It All Together
The rest of this article was written by Ty Ryan. Ty is a Systems Administrator and VMWare expert. He enjoys long walks on the beach and quiet evenings with his laptop.

Here are his instructions for adding this .msi to Active Directory Group Policy.

Assigning Applications via GPO’s

In this document we are going to discuss how to create Group Policy Objects in order to publish or assign applications create by OneClick. Only use this technique to deploy certain types of applications. Specifically, you can install Windows Installer packages (.MSI files), Transform Files (.MST files), and patch files (.MSP files).

Providing the application to assign

The very first step is to create an MSI which will be pushed via Group Policies Objects.
To create, manage, backup, import, or report group policy settings I would suggest using Microsoft’s GPMC (Group Policy Management Console) which provides a UI to better manage all GPO’s.
You can go directly to Microsoft’s site to get GPMC by clicking here and if you would like more information on managing group policies, follow this link.
To create your group policy right-click on the Active Directory OU you wish to apply or test it and click Create and Link a GPO Here…

image135.jpg

Now, provide a name for your GPO and click OK.

image137.jpg

Go ahead and right-click on the new GPO and click Edit.

image139.jpg

You will now be able to modify the settings necessary to install ClickOnce applications remotely.
Click on the “+” of Software Settings under User Configuration, then right-click on Software installation, New, Package…

image141.jpg

image143.jpg

Select Assigned to install the application the next time the user logs into Windows. More info about the difference between Published or Assigned applications can be found here. Be sure that the application to be assigned is in a centrally located share easily accessible by domain controllers and users.
Right-click on the newly created software installation assignment and click Properties.

image145.jpg

On the second tab, Deployment, be sure to select Install this application at Logon and then click OK.

image147.jpg

image149.jpg

If the application to be installed requires Local Administrator privileges for a successful deployment, then elevated privileges will have to be enabled within the GPO used to assign the application at next logon. This can be accomplished by enabling Always install with elevated privileges located under Computer and User Configuration, Administrative Templates, Windows Components, MSI Installer.

Advertisement

19 Comments

  1. hi,

    this is an excellent article, but there is a crucial problem with it now. Since Microsoft decided to remove the entire gotdotnet site. the following URL is missing:

    http://www.gotdotnet.com/codegallery/releases/viewuploads.aspx?id=941d2228-3bb5-42fd-8004-c08595821170

    Any idea where to get it from now? Or can you send me a copy of the resource kit via email?

    many thanks in advance,

    Bruce

  2. Bruce,

    Brian has moved the resource kit. Thanks for the heads up!! I will update the article shortly, but until then, you can find the kit here now: http://www.codeplex.com/smartclient/Project/FileDownload.aspx?DownloadId=5060

  3. Hi,

    Is there a way to add a click-once program to the add/remove program menu so the start menu item can be removed?

    Thanks,
    Sonia

  4. Sonia,

    If you choose the ‘The application is available offline as well’ Then not only will you get the start menu icons, but you get an entry in the add/remove programs as well. When removing the applications from the Add/Remove programs, you will also get the option to roll back to the previous version, as Windows keeps the last version around as well as the current one.

    Hope that answers your question….

    -Jeff

  5. Hi
    Thanks for a very informative article.
    Is there a way to link clickonce to a setup project so the installation url can be taken from the target virtual directory? I already store the target virtual directory name in my setup project, but the ClickOnce program won’t install since I don’t know where the user will publish the application from. Plus I can’t really share the c:\inetpub folder.
    I’ve read http://msdn2.microsoft.com/en-us/library/ms973805.aspx#clickoncevsinstaller_topic8 on how to combine them, but the details are very slim.
    Thanks
    Eti

  6. I am not sure what you mean by this. In this article I describe using an installer to place an icon on the desktop. The icon is a shortcut to the installer url. If the url is inside of your network, you can choose a share at \\machine\sharename\app.application instead of an http:// url. I don’t think I understand fully your problem, but if you can describe what you are trying to do in more detail, I might be able to help more.

    -Jeff

  7. Great article. I basically had done the same thing to publish my CAB application but I am running into a snag. When I run the app over the network the ProfileCatalog.xml is not being read as no modules are being loaded. I changed the Publish Status on all the files to include as you suggested but still nothing. I can copy the exact folder to my local and run the shell and the everything loads fine. It’s just when I execute the Click-Once generated application the ProfileCatalog.xml file is ignored it seems. Any help would be much appreciated.

    -Paul

  8. I had this same problem when I started with ClickOnce and CAB. I found that changing the publish status to include was the first step. The other problem that I ran into is that when you use CAB, by design it loosely couples the modules it uses. That means that there is no reference from the shell project to the modules. This is a problem for ClickOnce. You will need to add the modules manually and re-sign the manifest to get the modules to deploy. I describe this in the article under the heading “Sign and Deploy
    Signing and CAB”, more specifically the heading “Adding the Missing Files”.

    You can also check the files in the deploy folder. I would bet if you look at all of the files at the publish point (in the version folder) you will see a list of .deploy files. If you look, I bet all or some of your module dll’s are missing. Follow the procedure in the article and it should work just fine.

    Let me know how it works out, and get back to me with any problems.

    -Jeff

  9. All of the dlls are there, that’s not a problem. I noticed that when I first started, that modules were not being included in the manifest. I can take the exact folder that gets deployed copy it to my local execute the shell and the application works. Only when I use the Click-Once app the shell loads perfectly but loads as if the ProfileCatalog.xml was not there because none of the modules load.

  10. Lets take this one offline, and I will post the answer once we come to one. I’ll email you directly.

    -Jeff

  11. [From Paul Above]
    I got it working! I started changing things in the shell that were not being reflected after I published. The problem was I was never incrementing the build each time I made a change and I had allowed offline access. This made the newer code check return false and always used the old previous installed code even though I was deleting and republishing the code on the UNC file share. The first time I deployed I did not have all the dlls and the ProfileCatalog.xml was corrupt. I am guessing it used the old version until I uninstalled and changes the version number. Wow thanks so much for your help.

    -Paul

  12. This happened because Paul was deleting the contents of the deploy folder each time it did not work. The auto-increment feature saw an empty directory and therefore didn’t increment (as expected). The problem was that his client machine had already run that version in a broken state. Here is how to reproduce the problem:
    1. Bad version of manifest without required files is deployed with offline capabilities as version 1.0.0.0.
    2. Client tries to ClickOnce deploy/run 1.0.0.0, of course it doesn’t work.
    3. Delete contents of deploy folder.
    4. Publish new changes BUT leave version 1.0.0.0 in ClickOnce.
    5. Client tries to run ClickOnce deploy/run. Client will not d/l changes since it already has version 1.0.0.0 even though the files on server are newer, the version is the same and it has no way of knowing. Since the offline version of the files are present as 1.0.0.0. New files are ignored.

    To avoid this make sure the version on the server is always at least one revision above what the client has. You can have it auto increment and be correct if you don’t delete the deploy folder, that happens by itself as long as the box is checked in ClickOnce below the version boxes. You can clean it up at the end by re-setting the version to 1.0.0.0 and choosing a new deploy location that will be open to the public.

    Good find Paul glad I could help!!

    -Jeff

  13. I’m flabergasted that very few people seem to be are automating this task using Nant. Using VisualStudio and any other GUI tools is time consuming and error prone – like any manual task. How about writing up a version of automating the ClickOnce deployment process using Nant scripts.

  14. I tried to cover in this article what needs to be done on a subject that does not have a lot of documentation. I figured I would share and it took me a long time to put this article together in step-by-step manner it was written in.

    Automating things is a great way to make a repetitive tasks easier, but that was not the aim of this article. As far as I know (and I could be wrong) Nant does not have the ability to do things like signing a manifest with a secure certificate. Also other things like the side-by-side deployment would be difficult to automate (if at all possible).

    Rather than complain about how flabbergasted you are at everyone else’s behaviors, why not create this Nant script and share it? I would love to post it or link to your blog article if you can make it happen. It takes me about 5 minutes to do a deploy using the methods described in this article, but I do understand the power of repeatability and automation.

    Telling everyone how flabbergasted you are at them is not likely to make you many friends, but I am sure that wasn’t your aim.

    -Jeff

    • Manoj Chakrabarti
    • Posted November 28, 2007 at 6:43 am
    • Permalink
    • Reply

    Nice article. But my problem is someting different. In my SCSF application, I am using 2 office dll for Outlook integration. When I am deploying the application in client machine using Click-Once, it’s not working. But if I remove that module which is using these Dll’s its working fine. How can I handle these situation. My Dll is: Office.dll and the interop dll is: Microsoft.Office.Interop.Outlook.dll. How can I handle this situation? Please help.

    -Manoj

  15. Well the first thing you can do is to take Click Once out of the equation. Most times it is not a click once problem at all. What I suggest is to build your project normally. Then copy the files from the build (bin/debug if you are building in debug mode) to the deploy machine (the client). See if the program runs on the other machine this way. If it does, then compare the files you just copied to the click once list of files (with the .deploy extension). They MUST be an exact duplicate (other than the extension of course). You may find there are files missing. If the program does not run, then figure out what is missing on your client machine that is installed on the development machine. Feel free to write back and let me know your findings. If you can create me a small sample application I can provide and email address and I can try it here as well, but please follow the above first and let me know your findings.
    -Jeff

    • Manoj Chakrabarti
    • Posted November 28, 2007 at 4:01 pm
    • Permalink
    • Reply

    Thanks for your quick response. Before writing to you I tried all the steps specified by you and some more but all in vain. After writing you I removes all COM components from my PC, delete my application from local disk and get it back from VSS. Then published my application again, and it’s start working. I had no time to find out exact reason due to timeline of my project, but I think my Interop DLL’s RCW was corrupted.

    -Manoj

  16. I have a problem that is related but different. My application has a DLL that is called from another DLL. Of course, I had to work with ClickOnce in order to get the deployment to include the called DLL. Here is the problem: I publish to the test “website” on my development computer (XP Pro). All the files are there with the .deploy extension. I install the application from there to my local (development) computer. It gets installed in the usual target folder somewhere under Local Settings\Apps\2.0 etc. It runs without any problems. I change the name of the referenced DLL to something else, and, as expected, I get a message that it couldn’t be loaded, so I know that I am trying to load the DLL in the installation folder, not from somewhere else in my system. Now I go to my laptop running Vista and install the app from the same “website” (both computers are on the same network). All of the same files are installed in a similar location on the laptop, but when I run the application, I get the message that the referenced DLL cannot be loaded. Everything appears to be the same in both installation folders (all of the same files have the same dates and times). Why isn’t the referenced DLL loading on the Vista machine? The “parent” DLL is loading, but not the DLL that is called from the first.

  17. I have a problem with my clickonce, I follow your steps exactly to include my missing CAB files, and if I look in the deploy folder (app_1_0_0_0) all my files are there… when the client tries to install the application it tells them that there is a problem and ends the install. I have had a look at it, and the error log says that the manifest is invalid or missing.

    the manifest may not be valid or the file could not be opened.
    + Parsing and DOM creation of the manifest resulted in error. Following parsing errors were noticed:
    -HRESULT: 0x80070c81
    Start line: 0
    Start column: 0
    Host file:
    + Exception from HRESULT: 0x80070C81

    according to the path, it is complaining about the application manifest not the deployment manifest.


Leave a Reply

Fill in your details below or click an icon to log in:

Gravatar
WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.