{"id":162,"date":"2022-11-08T15:09:46","date_gmt":"2022-11-08T14:09:46","guid":{"rendered":"https:\/\/guillemrueda.com\/blog\/?p=162"},"modified":"2022-11-08T15:50:54","modified_gmt":"2022-11-08T14:50:54","slug":"clickonce-amb-net6","status":"publish","type":"post","link":"https:\/\/guillemrueda.com\/blog\/2022\/11\/08\/clickonce-amb-net6\/","title":{"rendered":"Clickonce amb Net6"},"content":{"rendered":"\n<p><strong>Funcions de System.Deployment.Application<\/strong><\/p>\n\n\n\n<p>Aquestes <a href=\"https:\/\/github.com\/dotnet\/deployment-tools\/issues\/9\">ja no estan disponibles amb NET6<\/a> [<a href=\"https:\/\/learn.microsoft.com\/en-us\/visualstudio\/deployment\/accessing-local-and-remote-data-in-clickonce-applications?view=vs-2022&amp;tabs=csharp\">i als docs se fa refer\u00e8ncia<\/a>] per\u00f2 afortunadament es poden simular via lectura de les variables d&#8217;entorn [<a href=\"https:\/\/github.com\/dotnet\/deployment-tools\/pull\/208\">informaci\u00f3 en aquesta request a github<\/a>] , dels fitxers de clickonce i dels directoris propis del desplegament.<\/p>\n\n\n\n<p>Fent servir part del codi d&#8217;exemple amb de desplegament de una aplicaci\u00f3 <a href=\"https:\/\/github.com\/derskythe\/WpfSettings\">NET6 WPF<\/a> com <a href=\"https:\/\/github.com\/simmotech\/Net6ClickOnce\">aquest luncher <\/a> he fet una llibreria tipificant les constants del desplegament que m\u00e9s fem servir aix\u00ed com simular el <em>update silenci\u00f3s<\/em> de clickonce que en realitat no \u00e9s un altre cosa que instal\u00b7lar per enrere i apagar la aplicaci\u00f3 un cop est\u00e0 instal\u00b7lada la nova versi\u00f3 (el <em>restart <\/em>de NET Framework ara no funcionar\u00e0):<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/Ruekov\/ClickOnceNET6\">https:\/\/github.com\/Ruekov\/ClickOnceNET6<\/a><\/p>\n\n\n\n<p><strong>MSBuild<\/strong><\/p>\n\n\n\n<p>La prefer\u00e8ncia de les aplicacions amb NET6 \u00e9s <em>preferible <\/em>utilitzar la comanda <em><a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/core\/tools\/dotnet-msbuild\">dotnet msbuild<\/a><\/em> el problema m\u00e9s important en aquest cas \u00e9s que clickonce es fonamenta b\u00e0sicament en NET Framework 3.5 aix\u00ed que haurem d&#8217;utilitzar MSBuild.<\/p>\n\n\n\n<p>Com passava ja amb MSBuild i clickonce, els perfils o les ordes de publicaci\u00f3 es comporten diferent amb Visual Studio que executades des MSBuild. A m\u00e9s a m\u00e9s, tenim el handicap de que les eines de <a href=\"https:\/\/github.com\/loresoft\/msbuildtasks\/\">msbuildtasks de loresoft<\/a> no acaben de funcionar b\u00e9. <\/p>\n\n\n\n<p>Per aquesta ra\u00f3 utilitzant els perfils de publicaci\u00f3 (<sub>Propierties\/PublicationProfiles\/ClickOnceProfile.pubxml<\/sub>) amb par\u00e0metres postcompilaci\u00f3 afegirem la tasca qu\u00e8:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Separi els fitxers de desplegament (setup.exe, xxxxx.application, launcher.exe i carpeta ApplicationFiles)<\/li>\n\n\n\n<li>Copi un template del index.html per personalitzar-lo (de nou MSBuild no \u00e9s capa\u00e7 de fer-lo posant-hi el WebPageFileName a true)<\/li>\n\n\n\n<li>Faci un ZIP amb els continguts del deplegament<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>\t&lt;Target Name=\"ZipPublishOutput\" AfterTargets=\"ZipDeployment\"&gt;\n\t\t&lt;ItemGroup&gt;\n\t\t\t&lt;LauncherFile Include=\"$(PublishDir)\\Launcher.exe\"\/&gt;\n\t\t\t&lt;ApplicationFile Include=\"$(PublishDir)\\$(MSBuildProjectName).application\"\/&gt;\n\t\t\t&lt;SetupFile Include=\"$(PublishDir)\\setup.exe\"\/&gt;\n\t\t\t&lt;ApplicationFiles Include=\"$(PublishDir)\\Application Files\\**\\*.*\"\/&gt;\n\t\t&lt;\/ItemGroup&gt;\n\t\t&lt;Copy SourceFiles=\"$(ProjectDir)\\index.html\" DestinationFiles=\"$(PublishDir)\\..\\..\\index.html\"\/&gt;\n\t\t&lt;WriteLinesToFile File=\"$(PublishDir)\\..\\..\\index.html\" Lines=\"$(&#91;System.Text.RegularExpressions.Regex]::Replace($(&#91;System.IO.File]::ReadAllText('$(PublishDir)\\..\\..\\index.html')), ''{AppVersion}'', ''$(AssemblyVersion)''))\" Overwrite=\"true\" Encoding=\"Unicode\" \/&gt;\n\t\t&lt;WriteLinesToFile File=\"$(PublishDir)\\..\\..\\index.html\" Lines=\"$(&#91;System.Text.RegularExpressions.Regex]::Replace($(&#91;System.IO.File]::ReadAllText('$(PublishDir)\\..\\..\\index.html')), ''{AppName}'', ''$(MSBuildProjectName)''))\" Overwrite=\"true\" Encoding=\"Unicode\" \/&gt;\n\t\t&lt;Copy\n\t\t\tSourceFiles=\"@(LauncherFile)\"\n\t\t\tDestinationFolder=\"$(PublishDir)\\..\\..\\\"\n        \/&gt;\n\t\t&lt;Copy\n            SourceFiles=\"@(SetupFile)\"\n            DestinationFolder=\"$(PublishDir)\\..\\..\\\"\n        \/&gt;\n\t\t&lt;Copy\n\t\t\tSourceFiles=\"@(ApplicationFile)\"\n\t\t\tDestinationFolder=\"$(PublishDir)\\..\\..\\\"\n        \/&gt;\n\t\t&lt;Copy\n            SourceFiles=\"@(ApplicationFiles)\"\n            DestinationFolder=\"$(PublishDir)\\..\\..\\Application Files\\%(RecursiveDir)\"\n        \/&gt;\n\t\t&lt;RemoveDir Directories=\"$(OutputPath)\" \/&gt;\n\t\t&lt;ZipDirectory SourceDirectory=\"$(PublishDir)\\..\\..\\\" DestinationFile=\"$(PublishDir)\\..\\..\\..\\PRO_$(MSBuildProjectName)_$(AssemblyVersion).zip\" Overwrite=\"true\" \/&gt;\n\t&lt;\/Target&gt;<\/code><\/pre>\n\n\n\n<p>Aquest Target haur\u00e0 de estar especificat al csproj del projecte:<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>\t&lt;Target Name=\"ZipDeployment\"&gt;\n\t&lt;\/Target&gt;\n<\/code><\/pre>\n\n\n\n<p>Al mateix csproj podrem afegir una tasca per mantenir actualitzat als prefils de publicaci\u00f3 el n\u00famero de versi\u00f3:<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>&lt;Target Name=\"updateVersionCLickOnce\"&gt;\n    &lt;PropertyGroup&gt;\n        &lt;FilePath&gt;.\\Properties\\PublishProfiles\\ClickOnceProfile.pubxml&lt;\/FilePathPRO&gt;\n    &lt;\/PropertyGroup&gt;\n    &lt;WriteLinesToFile File=\"$(FilePath)\" Lines=\"$(&#91;System.Text.RegularExpressions.Regex]::Replace($(&#91;System.IO.File]::ReadAllText('$(FilePath)')), '&amp;gt;\\d+\\.\\d+\\.\\d+\\.\\d+&amp;lt;', ''&amp;gt;$(AssemblyVersion)&amp;lt;''))\" Overwrite=\"true\" Encoding=\"Unicode\" \/&gt; \n&lt;\/Target&gt;<\/code><\/pre>\n\n\n\n<p>Al ser una tasca que hauria de ser executada abans de comen\u00e7ar la compilaci\u00f3 de la publicaci\u00f3 haurem de especificar-la al inici del XML del csproj:<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>&lt;Project Sdk=\"Microsoft.NET.Sdk\" InitialTargets=\"updateVersionCLickOnce\"&gt;\n<\/code><\/pre>\n\n\n\n<p>Ara ja podem executar el msbuild generant la sortida correcta i esperada:<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>msbuild \/t:Publish,ZipDeployment \/p:DeployOnBuild=true \/p:PublishProfile=ClickOnceProfile.xml \/restore<\/code><\/pre>\n\n\n\n<p><strong>Recursos<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Perfils de publicaci\u00f3 amb VS2022: <a href=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/host-and-deploy\/visual-studio-publish-profiles?view=aspnetcore-6.0\">https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/host-and-deploy\/visual-studio-publish-profiles?view=aspnetcore-6.0<\/a><\/li>\n\n\n\n<li>Perfils de publicaci\u00f3 amb VS2022: ClickOnce <a href=\"https:\/\/learn.microsoft.com\/en-us\/visualstudio\/deployment\/building-clickonce-applications-from-the-command-line?view=vs-2022\">https:\/\/learn.microsoft.com\/en-us\/visualstudio\/deployment\/building-clickonce-applications-from-the-command-line?view=vs-2022<\/a><\/li>\n\n\n\n<li>Crear un arxiu de projecte per a MSBuild: <a href=\"https:\/\/learn.microsoft.com\/en-us\/visualstudio\/msbuild\/walkthrough-creating-an-msbuild-project-file-from-scratch?view=vs-2022\">https:\/\/learn.microsoft.com\/en-us\/visualstudio\/msbuild\/walkthrough-creating-an-msbuild-project-file-from-scratch?view=vs-2022<\/a><\/li>\n\n\n\n<li>MSBuild doesn&#8217;t respect PublishUrl: <a href=\"https:\/\/stackoverflow.com\/questions\/1919625\/msbuild-doesnt-respect-publishurl-property-for-my-clickonce-app\">https:\/\/stackoverflow.com\/questions\/1919625\/msbuild-doesnt-respect-publishurl-property-for-my-clickonce-app<\/a><\/li>\n\n\n\n<li>Common MSBuild project propierties: <a href=\"https:\/\/learn.microsoft.com\/en-us\/visualstudio\/msbuild\/common-msbuild-project-properties?view=vs-2022\">https:\/\/learn.microsoft.com\/en-us\/visualstudio\/msbuild\/common-msbuild-project-properties?view=vs-2022<\/a><\/li>\n\n\n\n<li>Default.html page is not created: <a href=\"https:\/\/developercommunity.visualstudio.com\/t\/unable-to-publish-a-net-50-winforms-project-via-cl\/1457240\">https:\/\/developercommunity.visualstudio.com\/t\/unable-to-publish-a-net-50-winforms-project-via-cl\/1457240<\/a><\/li>\n\n\n\n<li>Publish with MSBuild: <a href=\"https:\/\/developercommunity.visualstudio.com\/t\/publish-with-msbuild\/848335\">https:\/\/developercommunity.visualstudio.com\/t\/publish-with-msbuild\/848335<\/a><\/li>\n\n\n\n<li>Clickonce not longer works: <a href=\"https:\/\/developercommunity.visualstudio.com\/t\/ClickOnce-no-longer-works\/1288425\">https:\/\/developercommunity.visualstudio.com\/t\/ClickOnce-no-longer-works\/1288425<\/a><\/li>\n\n\n\n<li>How to replace string in file using msbuild?: <a href=\"https:\/\/stackoverflow.com\/questions\/7837644\/how-to-replace-string-in-file-using-msbuild\">https:\/\/stackoverflow.com\/questions\/7837644\/how-to-replace-string-in-file-using-msbuild<\/a><\/li>\n\n\n\n<li>Using msbuild to execute a File System Publish Profile: <a href=\"https:\/\/stackoverflow.com\/questions\/16246562\/using-msbuild-to-execute-a-file-system-publish-profile\">https:\/\/stackoverflow.com\/questions\/16246562\/using-msbuild-to-execute-a-file-system-publish-profile<\/a><\/li>\n\n\n\n<li>Improve update detection for .NET (Core) applications deployed with ClickOnce <a href=\"https:\/\/github.com\/dotnet\/deployment-tools\/issues\/27\">https:\/\/github.com\/dotnet\/deployment-tools\/issues\/27<\/a><\/li>\n<\/ul>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Funcions de System.Deployment.Application Aquestes ja no estan disponibles amb NET6 [i als docs se fa refer\u00e8ncia] per\u00f2 afortunadament es poden simular via lectura de les variables d&#8217;entorn [informaci\u00f3 en aquesta request a github] , dels fitxers de clickonce i dels directoris propis del desplegament. Fent servir part del codi d&#8217;exemple amb de desplegament de una &hellip; <a href=\"https:\/\/guillemrueda.com\/blog\/2022\/11\/08\/clickonce-amb-net6\/\" class=\"more-link\">Continua la lectura de <span class=\"screen-reader-text\">Clickonce amb Net6<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7,16,17,1,6],"tags":[],"class_list":["post-162","post","type-post","status-publish","format-standard","hentry","category-net-programacio","category-clickonce","category-devops","category-general","category-programacio"],"_links":{"self":[{"href":"https:\/\/guillemrueda.com\/blog\/wp-json\/wp\/v2\/posts\/162","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/guillemrueda.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/guillemrueda.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/guillemrueda.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/guillemrueda.com\/blog\/wp-json\/wp\/v2\/comments?post=162"}],"version-history":[{"count":8,"href":"https:\/\/guillemrueda.com\/blog\/wp-json\/wp\/v2\/posts\/162\/revisions"}],"predecessor-version":[{"id":173,"href":"https:\/\/guillemrueda.com\/blog\/wp-json\/wp\/v2\/posts\/162\/revisions\/173"}],"wp:attachment":[{"href":"https:\/\/guillemrueda.com\/blog\/wp-json\/wp\/v2\/media?parent=162"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/guillemrueda.com\/blog\/wp-json\/wp\/v2\/categories?post=162"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/guillemrueda.com\/blog\/wp-json\/wp\/v2\/tags?post=162"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}