Depoy a ClickOnce-App from a Build-Server

ClickOnce (Wikipedia, MSDN) is an easy way to deploy and update your .NET-application. Its also easy to set it up in Visual Studio and run it from there. It increments the version-number, compiles and deploys the application in one and simple step. But I really don’t want to publish software with my IDE on a developer-machine. Of course I want initiate the deployment from a build-server. While ClickOnce-deployment works nicely within Visual Studio, it can be a real bitch running stand-alone.

Visual-Studio uses MSBuild to build stuff, so the first step is obvious. The ‘publish’-target creates the ClickOnce-Installer etc. Go to your project, open the console and try it.

%windir%\Microsoft.Net\Framework\v3.5\msbuild.exe /target:Publish /property:Configuration=Release

However running the ‘publish’-target won’t update the version-number nor copy it to the target (documented here). This only works within Visual Studio. But this isn’t necessarily a bad thing, because now you have full control over it. The revision is set with the  ApplicationRevision-property:

%windir%\Microsoft.Net\Framework\v3.5\msbuild.exe /target:Publish /property:Configuration=Release;ApplicationRevision=42

This way you can set this property with your build-server. So its possible to synchronize application-versions with build-runs or something else. The published files are in the “%Project%/Release/app.publish/”-Directory, ready to copy to the server. So the best way is to write a little MSBuild-script. In my example I invoke just the ordinary-build-target and copy then the files to a server. The ApplicationRevision-property is set externally by the build-server or command-line:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Publish" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <!-- project name-->
    <ProjectName>MyExampleProject</ProjectName>
    <!--properties for the project-build-->
    <DefaultBuildProperties>Configuration=Release</DefaultBuildProperties>
    <!-- location of the click-once stuff, relative to the project -->
    <ProjectPublishLocation>.\bin\Release\app.publish</ProjectPublishLocation>
    <!-- Location you want to copy the click-once-deployment. Here an windows-share-->
    <ProjectClickOnceFolder>\\TargetServer\deployments</ProjectClickOnceFolder>
  </PropertyGroup>
  <Target Name="Publish" DependsOnTargets="Clean">
    <Message Text="Publish-Build started for build no $(ApplicationRevision)" />
    <!-- run the original build of the project -->
    <MSBuild Projects="./$(ProjectName).csproj"
    Properties="$(DefaultBuildProperties)"
    Targets="Publish"/>
    <!-- define the files required for click-once-->
    <ItemGroup>
      <SetupFiles Include="$(ProjectPublishLocation)\*.*"/>
      <UpdateFiles Include="$(ProjectPublishLocation)\Application Files\**\*.*"/>
    </ItemGroup>
    <!-- and copy them -->
    <Copy
    SourceFiles="@(SetupFiles)"
    DestinationFolder="$(ProjectClickOnceFolder)\"/>
    <Copy
    SourceFiles="@(UpdateFiles)"
    DestinationFolder="$(ProjectClickOnceFolder)\Application Files\%(RecursiveDir)"/>
  </Target>
  <Target Name="Clean">
    <Message Text="Clean project" />
    <MSBuild Projects="./$(ProjectName).csproj"
    Properties="$(DefaultBuildProperties)"
    Targets="Clean"/>
  </Target>
</Project>

After running, testing and improving the deploy-process, try it out on your build-server. If it runs your lucky. But, your build will probably fail with a message like: “setup.bin” not found in “ExampleProject/Engine”.

Now things start to get ugly, really really ugly. You need the ‘bootstrapper’-files to build the click-once-setup. This files are located normally under ‘C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bootstrapper’. (And installed by Visual Studio. But I really don’t want Visual Studio on my build-machine). So copy them to your build-machine. Then you add this registry-key:

Key Name:          HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\GenericBootstrapper\3.5

Value Name: Path
Type: REG_SZ
Data: c:\CopiedFiles\

Run the build-scrip again on the server. If it works now, well done. If it still fails with an error like this: “Signtool requires CAPICOM version 2.1.0.1” it gets even uglier!

Download the CAPICOM SDK here. Install/Extract it. There will be a ‘capicom.dll’ in it. You can copy it to the %windir%/system32. Then you need this register it. Run with administrator-privileges “REGSVR32 capicom.dll”. Finally your build should run.  \o/

If you know a better way to run ClickOnce-deployment without Visual-Studio and without hacks, please tell me. Its really ugly at the moment.

Sources and references:

One thought on “Depoy a ClickOnce-App from a Build-Server