ClickOnce Deployment with the TFS Build Process
When you deploy a Visual Studio application from your own development environment via ClickOnce, it is just about the easiest thing you can do. You'd hope it would be just as easy when using the TFS build process but unfortunately it is not (as you may have found out if you tried to do it and started running into roadblocks). Using the .targets file that we provide takes care of all the problems for you on the back end, making a potentially complicated sign and deploy process much simpler. We will explain the process to you for your own education, however you can simply install a NuGet Package that we have created for you that will dump everything you need into your project.
- 1 Concept
- 2 Installation Steps
- 3 Build Output
Like most things, none of this is difficult once you have done it once and understand what is happening. When building locally, Visual Studio will not publish a ClickOnce deployment by default (a separate menu item must be selected). And the build server cannot do this for you. So you must change this behavior to have the project published to your build output each time. Once the build server gets this output on each build, we can automate the process of signing and copying our output as needed.
Note: Signing code is different from signing manifests. This information applies to manifests.
Manifest Signing Keys
You must have keys to sign manifests just like code signing. These keys have either already been created for you in a secure location on the network, or you may need to contact the Stack Team to have it created for you. The key name is based on your portfolio. If your portfolio prefix was "GA" then your network key is named GAClickOncePrivateKey.pvk and GAClickOncePublicKey.cer.
Creating a publish automatically with each build
Changing your project to create a published application on each build is simple. When editing your csproj file you change your DefaultTargets in the Project tag to look like this:
Editing variables for multiple environments
In a single environment this part would not be necessary, but in a real scenario with multiple build environments these variables must be set. In a custom targets file, we create these Properties which override the ones set in Visual Studio in the Publish tab.
<InstallUrl Condition=" '$(Configuration)' == 'Debug' ">http://ClickOncePublishServer-Debug/app/</InstallUrl> <ApplicationTitle>My App</ApplicationTitle> <PublisherName>LDS Church</PublisherName> <SupportUrl>http://intranet/MyApp</SupportUrl> <ProductName>$(ApplicationTitle)</ProductName>
Signing the manifests
We will sign the application and deployment manifests:
- Using the mage.exe utility, we sign the application manifest with our private key.
- Now the application manifest is no longer the file that was originally hashed as part of the application manifest so we need to update the development manifest with mage.
- Now that the deployment manifest has changed, we can sign it because this is what our final deployment manifest will look like. Even if it has been previously signed this must be done again because the hash on the initial signing would be different than the new hash with the updated application manifest.
Installing ClickOnce NuGet package
Using the package manager in Visual Studio, install the package LDS Stack ClickOnce Deployment.
Project Specific Settings
This prompt assumes you have a Debug configuration and a Release configuration. After installation you can modify these to account for your unique situation if it is different than this.
The following items will have been added to your project:
- Build Solution Folder (containing MSBuild community tasks and the ClickOnce .targets file)
- SlowCheetah Solution Folder (for doing transforms on
- default.template.htm (for creating the ClickOnce html publish page)
Your .csproj file will have had the following import statements added:
<Import Project="$(SolutionDir)\Build\MSBuild.Community.Tasks.targets" /> <Import Project="$(SolutionDir)\SlowCheetah\v1\SlowCheetah.Transforms.targets" /> <Import Project="$(SolutionDir)\build\Lds.Stack.ClickOnceDeployment.targets" />
Here is what you will find in your project's drop folder after a successful build:
Client Certificate Installer
Starting in the root folder of the actual build output you will see a Packages folder which contains a .zip file. This is the file you would distribute to customers should you want their machines to trust the certificate you have signed your deployment with. A customer would unzip this file into an empty folder on their machine and simply double click the provided batch file. The certificate will automatically be installed.
This is not required but it will make it so your customer won't get a security warning when they run your application.
Finished ClickOnce Deployment Files
Under the Packages folder, each build configuration will have a folder called Client that contains the files to copy to your deployment location.
Also, copy the files for the latest version of your application that you will find under the Application Files folder.