Clickonce deployment to multiple environments
Asked Answered
R

3

18

I have a WPF application that I want to deploy to our users via ClickOnce. We have four environments, System Testing, User Testing, Parallel production and Production. Each needs a different config file with server names and other things specific to the environment so they cannot all use the same code base. Most of the code is the same but the final package will be slightly different because of the different .config files.

What I'm finding is that we install a version in user testing, say version 05, then they test, and then when it comes time to give them the next version, we should just be able to put an updated package on the user test web server, then they can update their version by clicking on the deployment URL. But when they do this it says "application with the same identity already exists" and we have to uninstall through control panel in order to get version 06 to install. This seems wrong and not the point of clickonce.

How would you suggest I build and deploy this application to the four different environments so that in each environment we have the capability of just putting a new version on the server and the users testing or using it from that environment will just pull down the update and not need to uninstall anything?

Render answered 8/2, 2013 at 14:53 Comment(0)
J
18

Having been looking for a solution myself for some time, it struck me that the final one I came up with is actually as simple as this:

  • Slow Cheetah for transforming the config files based on the selected build configuration (e.g. Debug/Release)
  • A property group per Build Configuration with the specific click-once project properties (e.g. ProductName and AssemblyName (for parallel installation of test and prod version), InstallUrl) in the project file.
  • Specifying additional properties (like ApplicationVersion, MinimumRequiredVersion) via msbuild when executing the /target:publish

There is no need to copy any config files manually as slow cheetah will handle this. The click once package will be created in the respective build configuration's output folder (e.g. bin/Debug or whatever you have).

The biggest advantage is that the build is the same for using Visual Studio or automatic builds using msbuild (except for the few additional properties which are completely optional). All you have to do to add additional environments to your build is to create new build configurations and the respective slow cheetah transformations and a property group in the project file.

The whole setup is working at least with .NET 3.5 (can't speak about earlier versions) and later.

Maybe this helps anyone. Feel free to ask for details.

PS: The property groups look like this (put them after the first property group that defines the default ClickOnce settings):

  <PropertyGroup Condition=" '$(Configuration)' == 'Demo' ">
    <AssemblyName>Com.MyApplication.Main.Demo</AssemblyName>
    <InstallUrl>http://demoserver/myapp/</InstallUrl>
    <ProductName>My Application %28Demo%29</ProductName>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)' == 'Test' ">
    <AssemblyName>Com.MyApplication.Main.Test</AssemblyName>
    <InstallUrl>http://testserver/myapp/</InstallUrl>
    <ProductName>My Application %28Test%29</ProductName>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)' == 'Prod' ">
    <AssemblyName>Com.MyApplication.Main</AssemblyName>
    <InstallUrl>http://prodserver/myapp/</InstallUrl>
    <ProductName>My Application</ProductName>
  </PropertyGroup>
Jerlenejermain answered 17/6, 2014 at 7:29 Comment(5)
How do you keep Visual Studio from over writing the InstallUrl, UpdateURl, and ProductName properties whenever you change the build configuration?Hartzel
@Hartzel Well, actually I don't. The property groups should not be changed as long as you don't open the project property page in Visual Studio. Additionally, source control makes sure that at least you notice and have the chance to revert if something goes wrong. Still a lot better than using mage...Jerlenejermain
This worked for me but I wanted to me mention an issue I ran into in case anyone else does. I kept getting the following error whenever I ran my production build: 'Provide value on 'System.Windows.Baml2006.TypeConverterMarkupExtension' threw an exception.' Turns out I was referencing my favicon using the initial assembly name(my.app/Images/fav.ico). Since this was a prod build the assembly build was changed to my.app.prod and the whole thing would blow up while initializing. I switched to using a relative path(/Images/fav.ico) and the problem went away.Ranzini
I'm assuming then you need to call msbuild three times, once for each environment, to generate a unique package for each environment?Cup
PropertyGroups work great for building from the command-line. However, msbuild doesn't sign the ClickOnce manifest, so you still need to use the Publish tab. This is tricky. You have to change the configuration and reload the project to get the correct PropertyGroup to load into the project. Still, it's better than changing the values manually.Samy
S
3

First, you can't install an application with the same deployment name from two different URLs without having to uninstall one first. ClickOnce uses this for security to make sure someone doesn't try to hijack your deployment.

Second, to do different builds, you can set up four folders under the project, one with each name. Then set up four build configurations (call them the same thing). Then set up a post-build command that copies the files into \bin folder. If you set up the folder names to have the build configuration in them, it will copy whichever ones go with that configuration.

COPY/Y "$(TargetDir)myfile_$(ConfigurationName)\*.*" "$(TargetDir)"

Third, you have to include the files in the project itself so they will be marked to be included in the deployment, even if you are replacing them with a copy command after the build is done. AND the four directories have to be included as well, even though ultimately they aren't used.

Schedule answered 25/2, 2013 at 7:43 Comment(1)
I'm not sure this will work when the publish manifest will still be referring to the original server? And you cant hand-edit the manifest file because isn't it signed?Heavyhanded
P
0

I had to add

<AssemblyName>ProdApp</AssemblyName> 

to .csproj as the default, then a conditional

<PropertyGroup Condition=" '$(Configuration)' == 'Staging' ">
    <AssemblyName>StagingApp</AssemblyName>
</PropertyGroup>

then created two .pubxmls

and set a different

<InstallUrl></InstallUrl>
<ProductName></ProductName>

in each.

Paucker answered 12/1, 2023 at 1:52 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.