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
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 126.96.36.199” 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:
- ClickOnce: http://msdn.microsoft.com/en-us/library/t71a733d(VS.80).aspx
- MSBuild: http://msdn.microsoft.com/en-us/library/0k6kkbsd.aspx
- MSBuild and ClickOnce: http://msdn.microsoft.com/en-us/library/ms165431(VS.80).aspx
- Bootstrapper/setup.bin-registry-hack: http://social.msdn.microsoft.com/Forums/en-US/msbuild/thread/7672078f-f2bd-4142-b8a9-740c2a8a5ae7
- Being Human