Over a million developers have joined DZone.

Deploying a Click-once Application With Build vNext in Azure Blob Storage

DZone 's Guide to

Deploying a Click-once Application With Build vNext in Azure Blob Storage

A tutorial on using Azure Blog Storage and how to deploy a click-once app to the service.

· Cloud Zone ·
Free Resource

Thanks to the new build system in TFS / VSTS, publishing an application with Click-once during a build is really simple.

Versioning the Click-once App

The project is using Git and GitFlow, thus it comes natural to use GitVersion (as described in a previous post) to automatically add Semantic Versioning. In previous post I’ve demonstrated how to use this technique to publish Nuget Packages and nothing changes for Click Once applications.

Thanks to GitVersion and GitFlow I do not need to care about version management of my project.

The only difference is in how numbering is created for ClickOnce applications. Click-once does not support suffix like –unstable or –beta as Nuget can support for pre-release package. To have a good Major.Minor.Path.Suffix number the solution is splitting the prerelease tag (ex –unstable.3) to grab only the last number part. The result is: instead of having  version 1.2.5-unstable7 (perfectly valid for nuget but not for click-once) the build will use version, perfectly valid for ClickOnce.

The whole operation is simply managed by powershell script.

$splitted = $preReleaseTag.Split('.')
$preReleaseNum = $splitted[$splitted.Length - 1]
if ([string]::IsNullOrEmpty($preReleaseNum))
    $preReleaseNum = "0"
$clickOnceVersion = $version.MajorMinorPatch + "." + $preReleaseNum

Building a Click-once Package

In MSDN official documentation there is a nice page that explain how to publish click-once application from command line with MSBuild. This is an exceptional starting point, because parameters can be easily passed to MSBuild during vNext build thus we need no customization to create click-once package.

Publishing with MSBuild command line interface makes easy to integrate in vNext Build.

First step is to declare a bunch of Build Properties in the build, to store all needed values during the build.


Figure 1: Variables to add for vNext build

The build needs three variables: $(ClickOnceVersion) will contain the version generated by with GitVersion, $(AzureBlobUrl) will contain the address of Azure Blob Url where the application will be published, and finally $(AzureBlobPrefix) is the prefix (folder) to categorize publishing. Basically, it is the subfolder in the Azure Blob where the files will be copied.

Powershell script does some sting manipulation to detect whitch branch is about to be published. Thanks to GitVersion in $preReleaseTag variable the build can know the logical branch that is about to be compiled (ex: unstable.1). If it is empty, the build is building the stable branch, if it is not null a simple split by dot character gives the logical branch: unstable, beta, etc. Using GitVersion preReleaseTag is better than checking branch name, because it better explains the role of current branch in GitFlow.

Knowing the logical branch (stable, unstable, beta) allows the build to publish different version of the product (stable, beta, unstable) on different subdirectory of azure blob.

This technique allows people to choose the distribution they want, similar to what Chrome does.

$preReleaseString = $splitted[0]
if ([string]::IsNullOrEmpty($preReleaseString))
    $preReleaseString = "stable"
    $ProductName = "MDbGui.Net"
    $ProductName = "MDbGui.Net-$preReleaseString"

Now that all variables are ready, it is time to specify MSBuild arguments to the task that builds the solution, and this is the only modification needed to trigger publishing the click-once package. These are the command line options needed to publish the click-once package from MSBuild:


Handling Artifacts

Previous MSBuild command line produces all files needed for click-once publishing inside a subdirectory called app.publish inside the output directory. To have a clean and nice build, it is better to copy all relevant files inside the staging directory.

This procedure was fully described in a previous post that dealt with managing artifacts in a vNext Build. I always prefer including a script to copying all files that need to be published for the build inside the staging directory, instead of relying on publishing every file inside bin folders.


Figure 2: Call a PowerShell script to copy all relevant files on Staging Directory

At the end of this step, all click-once related files are placed inside a subfolder of the staging directory. The last step is moving those files on a web site or Azure Blob Storage. Click-once apps need only to be placed on an accessible site. An instance of IIS is perfectly valid, but cost of Azure Blob Storage is really low and there is already a nice Build vNext task to copy files on it, so it would be stupid not to take advantage of it.

Move Everything on Azure Blob

The easiest solution to copy all click-once related file on a public accessible location is creating a public Azure Blob Storage, because you already have an action in build vNext to accomplish this task.


Figure 3: Azure Blob File copy task can copy files easily in target Blob Storage

To connect an Azure Account with Azure Endpoint, please consult my previous post on the argument: Use the right Azure Service Endpoint in build vNext to avoid my mistake of trying to access a classic Blob Storage with Azure ARM.

As you can see from figure 3, I specified the name of the storage acount, the container name, and a prefix that is used to publish different branches for the application.

At the end of the build you have your application published on a url like this one: https://portalvhdsdlrhmlyhqzrk1.blob.core.windows.net/mdbgui/unstable/MDbGui.Net.application


All the scripts used to create this articles are in this project: https://github.com/stefanocastriotta/MDbGui.Net/tree/develop/Tools/BuildScripts 

You can download them and use in your project if you want. Thanks to the ability to change build numbers here is the result:


Figure 4: You can easily find the version number in build number.


Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}