{"id":394,"date":"2009-05-19T21:01:18","date_gmt":"2009-05-19T20:01:18","guid":{"rendered":"http:\/\/www.gamlor.info\/wordpress\/?p=394"},"modified":"2021-03-11T09:44:41","modified_gmt":"2021-03-11T08:44:41","slug":"depoy-a-clickonce-app-from-a-build-server","status":"publish","type":"post","link":"https:\/\/www.gamlor.info\/wordpress\/2009\/05\/depoy-a-clickonce-app-from-a-build-server\/","title":{"rendered":"Depoy a ClickOnce-App from a Build-Server"},"content":{"rendered":"<p><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/t71a733d(VS.80).aspx\">ClickOnce<\/a> (<a href=\"http:\/\/en.wikipedia.org\/wiki\/ClickOnce\">Wikipedia<\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/t71a733d(VS.80).aspx\">MSDN<\/a>) 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\u2019t 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.<\/p>\n<p>Visual-Studio uses <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/0k6kkbsd.aspx\">MSBuild<\/a> to build stuff, so the first step is obvious. The \u2018publish\u2019-target creates the ClickOnce-Installer etc. Go to your project, open the console and try it.<\/p>\n<blockquote><p>%windir%\\Microsoft.Net\\Framework\\v3.5\\msbuild.exe \/target:Publish \/property:Configuration=Release<\/p><\/blockquote>\n<p>However running the \u2018publish\u2019-target won\u2019t update the version-number nor copy it to the target (<a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms165431(VS.80).aspx\">documented here<\/a>). This only works within Visual Studio. But this isn\u2019t necessarily a bad thing, because now you have full control over it. The revision is set with the\u00a0 ApplicationRevision-property:<\/p>\n<blockquote><p>%windir%\\Microsoft.Net\\Framework\\v3.5\\msbuild.exe \/target:Publish \/property:Configuration=Release;ApplicationRevision=42<\/p><\/blockquote>\n<p>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 \u201c%Project%\/Release\/app.publish\/\u201d-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:<\/p>\n<pre class=\"csharpcode\"><span class=\"kwrd\">&lt;?<\/span><span class=\"html\">xml<\/span> <span class=\"attr\">version<\/span><span class=\"kwrd\">=\"1.0\"<\/span> <span class=\"attr\">encoding<\/span><span class=\"kwrd\">=\"utf-8\"<\/span>?<span class=\"kwrd\">&gt;<\/span>\r\n<span class=\"kwrd\">&lt;<\/span><span class=\"html\">Project<\/span> <span class=\"attr\">ToolsVersion<\/span><span class=\"kwrd\">=\"3.5\"<\/span> <span class=\"attr\">DefaultTargets<\/span><span class=\"kwrd\">=\"Publish\"<\/span> <span class=\"attr\">xmlns<\/span><span class=\"kwrd\">=\"http:\/\/schemas.microsoft.com\/developer\/msbuild\/2003\"<\/span><span class=\"kwrd\">&gt;<\/span>\r\n  <span class=\"kwrd\">&lt;<\/span><span class=\"html\">PropertyGroup<\/span><span class=\"kwrd\">&gt;<\/span>\r\n    <span class=\"rem\">&lt;!-- project name--&gt;<\/span>\r\n    <span class=\"kwrd\">&lt;<\/span><span class=\"html\">ProjectName<\/span><span class=\"kwrd\">&gt;<\/span>MyExampleProject<span class=\"kwrd\">&lt;\/<\/span><span class=\"html\">ProjectName<\/span><span class=\"kwrd\">&gt;<\/span>\r\n    <span class=\"rem\">&lt;!--properties for the project-build--&gt;<\/span>\r\n    <span class=\"kwrd\">&lt;<\/span><span class=\"html\">DefaultBuildProperties<\/span><span class=\"kwrd\">&gt;<\/span>Configuration=Release<span class=\"kwrd\">&lt;\/<\/span><span class=\"html\">DefaultBuildProperties<\/span><span class=\"kwrd\">&gt;<\/span>\r\n    <span class=\"rem\">&lt;!-- location of the click-once stuff, relative to the project --&gt;<\/span>\r\n    <span class=\"kwrd\">&lt;<\/span><span class=\"html\">ProjectPublishLocation<\/span><span class=\"kwrd\">&gt;<\/span>.\\bin\\Release\\app.publish<span class=\"kwrd\">&lt;\/<\/span><span class=\"html\">ProjectPublishLocation<\/span><span class=\"kwrd\">&gt;<\/span>\r\n    <span class=\"rem\">&lt;!-- Location you want to copy the click-once-deployment. Here an windows-share--&gt;<\/span>\r\n    <span class=\"kwrd\">&lt;<\/span><span class=\"html\">ProjectClickOnceFolder<\/span><span class=\"kwrd\">&gt;<\/span>\\\\TargetServer\\deployments<span class=\"kwrd\">&lt;\/<\/span><span class=\"html\">ProjectClickOnceFolder<\/span><span class=\"kwrd\">&gt;<\/span>\r\n  <span class=\"kwrd\">&lt;\/<\/span><span class=\"html\">PropertyGroup<\/span><span class=\"kwrd\">&gt;<\/span>\r\n  <span class=\"kwrd\">&lt;<\/span><span class=\"html\">Target<\/span> <span class=\"attr\">Name<\/span><span class=\"kwrd\">=\"Publish\"<\/span> <span class=\"attr\">DependsOnTargets<\/span><span class=\"kwrd\">=\"Clean\"<\/span><span class=\"kwrd\">&gt;<\/span>\r\n    <span class=\"kwrd\">&lt;<\/span><span class=\"html\">Message<\/span> <span class=\"attr\">Text<\/span><span class=\"kwrd\">=\"Publish-Build started for build no $(ApplicationRevision)\"<\/span> <span class=\"kwrd\">\/&gt;<\/span>\r\n    <span class=\"rem\">&lt;!-- run the original build of the project --&gt;<\/span>\r\n    <span class=\"kwrd\">&lt;<\/span><span class=\"html\">MSBuild<\/span> <span class=\"attr\">Projects<\/span><span class=\"kwrd\">=\".\/$(ProjectName).csproj\"<\/span>\r\n    <span class=\"attr\">Properties<\/span><span class=\"kwrd\">=\"$(DefaultBuildProperties)\"<\/span>\r\n    <span class=\"attr\">Targets<\/span><span class=\"kwrd\">=\"Publish\"<\/span><span class=\"kwrd\">\/&gt;<\/span>\r\n    <span class=\"rem\">&lt;!-- define the files required for click-once--&gt;<\/span>\r\n    <span class=\"kwrd\">&lt;<\/span><span class=\"html\">ItemGroup<\/span><span class=\"kwrd\">&gt;<\/span>\r\n      <span class=\"kwrd\">&lt;<\/span><span class=\"html\">SetupFiles<\/span> <span class=\"attr\">Include<\/span><span class=\"kwrd\">=\"$(ProjectPublishLocation)\\*.*\"<\/span><span class=\"kwrd\">\/&gt;<\/span>\r\n      <span class=\"kwrd\">&lt;<\/span><span class=\"html\">UpdateFiles<\/span> <span class=\"attr\">Include<\/span><span class=\"kwrd\">=\"$(ProjectPublishLocation)\\Application Files\\**\\*.*\"<\/span><span class=\"kwrd\">\/&gt;<\/span>\r\n    <span class=\"kwrd\">&lt;\/<\/span><span class=\"html\">ItemGroup<\/span><span class=\"kwrd\">&gt;<\/span>\r\n    <span class=\"rem\">&lt;!-- and copy them --&gt;<\/span>\r\n    <span class=\"kwrd\">&lt;<\/span><span class=\"html\">Copy<\/span>\r\n    <span class=\"attr\">SourceFiles<\/span><span class=\"kwrd\">=\"@(SetupFiles)\"<\/span>\r\n    <span class=\"attr\">DestinationFolder<\/span><span class=\"kwrd\">=\"$(ProjectClickOnceFolder)\\\"<\/span><span class=\"kwrd\">\/&gt;<\/span>\r\n    <span class=\"kwrd\">&lt;<\/span><span class=\"html\">Copy<\/span>\r\n    <span class=\"attr\">SourceFiles<\/span><span class=\"kwrd\">=\"@(UpdateFiles)\"<\/span>\r\n    <span class=\"attr\">DestinationFolder<\/span><span class=\"kwrd\">=\"$(ProjectClickOnceFolder)\\Application Files\\%(RecursiveDir)\"<\/span><span class=\"kwrd\">\/&gt;<\/span>\r\n  <span class=\"kwrd\">&lt;\/<\/span><span class=\"html\">Target<\/span><span class=\"kwrd\">&gt;<\/span>\r\n  <span class=\"kwrd\">&lt;<\/span><span class=\"html\">Target<\/span> <span class=\"attr\">Name<\/span><span class=\"kwrd\">=\"Clean\"<\/span><span class=\"kwrd\">&gt;<\/span>\r\n    <span class=\"kwrd\">&lt;<\/span><span class=\"html\">Message<\/span> <span class=\"attr\">Text<\/span><span class=\"kwrd\">=\"Clean project\"<\/span> <span class=\"kwrd\">\/&gt;<\/span>\r\n    <span class=\"kwrd\">&lt;<\/span><span class=\"html\">MSBuild<\/span> <span class=\"attr\">Projects<\/span><span class=\"kwrd\">=\".\/$(ProjectName).csproj\"<\/span>\r\n    <span class=\"attr\">Properties<\/span><span class=\"kwrd\">=\"$(DefaultBuildProperties)\"<\/span>\r\n    <span class=\"attr\">Targets<\/span><span class=\"kwrd\">=\"Clean\"<\/span><span class=\"kwrd\">\/&gt;<\/span>\r\n  <span class=\"kwrd\">&lt;\/<\/span><span class=\"html\">Target<\/span><span class=\"kwrd\">&gt;<\/span>\r\n<span class=\"kwrd\">&lt;\/<\/span><span class=\"html\">Project<\/span><span class=\"kwrd\">&gt;<\/span><\/pre>\n<p>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: \u201csetup.bin\u201d not found in \u201cExampleProject\/Engine\u201d.<\/p>\n<p>Now things start to get ugly, really really ugly. You need the \u2018bootstrapper\u2019-files to build the click-once-setup. This files are located normally under \u2018C:\\Program Files\\Microsoft SDKs\\Windows\\v6.0A\\Bootstrapper\u2019. (And installed by Visual Studio. But I really don\u2019t want Visual Studio on my build-machine). So copy them to your build-machine. Then you add this registry-key:<\/p>\n<blockquote><p>Key Name:\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\GenericBootstrapper\\3.5<\/p>\n<p>Value Name: Path<br \/>\nType: REG_SZ<br \/>\nData: c:\\CopiedFiles\\<span style=\"color: #555555;\"> <\/span><\/p><\/blockquote>\n<p>Run the build-scrip again on the server. If it works now, well done. If it still fails with an error like this: \u201cSigntool requires CAPICOM version 2.1.0.1\u201d it gets even uglier!<\/p>\n<p>Download the <a href=\"http:\/\/www.microsoft.com\/downloads\/details.aspx?FamilyID=860ee43a-a843-462f-abb5-ff88ea5896f6&amp;DisplayLang=en\">CAPICOM SDK here<\/a>. Install\/Extract it. There will be a \u2018capicom.dll\u2019 in it. You can copy it to the %windir%\/system32. Then you need this register it. Run with administrator-privileges \u201cREGSVR32 capicom.dll\u201d. Finally your build should run.\u00a0 \\o\/<\/p>\n<p>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.<\/p>\n<p>Sources and references:<\/p>\n<ul>\n<li>ClickOnce: <a title=\"http:\/\/msdn.microsoft.com\/en-us\/library\/t71a733d(VS.80).aspx\" href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/t71a733d(VS.80).aspx\">http:\/\/msdn.microsoft.com\/en-us\/library\/t71a733d(VS.80).aspx<\/a><\/li>\n<li>MSBuild: <a title=\"http:\/\/msdn.microsoft.com\/en-us\/library\/0k6kkbsd.aspx\" href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/0k6kkbsd.aspx\">http:\/\/msdn.microsoft.com\/en-us\/library\/0k6kkbsd.aspx<\/a><\/li>\n<li>MSBuild and ClickOnce: <a title=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms165431(VS.80).aspx\" href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms165431(VS.80).aspx\">http:\/\/msdn.microsoft.com\/en-us\/library\/ms165431(VS.80).aspx<\/a><\/li>\n<li>Bootstrapper\/setup.bin-registry-hack: <a title=\"http:\/\/social.msdn.microsoft.com\/Forums\/en-US\/msbuild\/thread\/7672078f-f2bd-4142-b8a9-740c2a8a5ae7\" href=\"http:\/\/social.msdn.microsoft.com\/Forums\/en-US\/msbuild\/thread\/7672078f-f2bd-4142-b8a9-740c2a8a5ae7\">http:\/\/social.msdn.microsoft.com\/Forums\/en-US\/msbuild\/thread\/7672078f-f2bd-4142-b8a9-740c2a8a5ae7<\/a><\/li>\n<li>CAPICOM-Hack:<a title=\"http:\/\/geekswithblogs.net\/hinshelm\/archive\/2007\/02\/07\/105684.aspx\" href=\"http:\/\/geekswithblogs.net\/hinshelm\/archive\/2007\/02\/07\/105684.aspx\">http:\/\/geekswithblogs.net\/hinshelm\/archive\/2007\/02\/07\/105684.aspx<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>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&hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[126,17,19],"tags":[21,110,112,111],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/394"}],"collection":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/comments?post=394"}],"version-history":[{"count":11,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/394\/revisions"}],"predecessor-version":[{"id":3821,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/394\/revisions\/3821"}],"wp:attachment":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/media?parent=394"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/categories?post=394"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/tags?post=394"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}