Clickonce deployment to multiple environments

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?


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 (eg Debug/Release)
  • A property group per Build Configuration with the specific click-once project properties (eg 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 (eg 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>
    

    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.


    I have been trying to do the same over the past two days with no luck. My current method does the following:

    msbuild /t:clean /p:Configuration=Release;PlatformTarget=x86 "C:ProductProduct.csproj
    del c:Productapp.config
    ren C:Productsystest.config C:Productapp.config
    msbuild /t:publish /p:Configuration=Release;PlatformTarget=x86;UpdateEnabled=true;UpdateMode=Foreground;UpdatePeriodically=false;MinimumRequiredVersion=2013.2.1086.5496;ApplicationVersion=2013.2.1086.5496;UpdateRequired=true;ProductName="System Test Product";InstallUrl="http://systest.product.temp-uri.org/install/"
    ren C:ProductbinReleaseapp.publish systest.app.publish
    
    msbuild /t:clean /p:Configuration=Release;PlatformTarget=x86 "C:ProductProduct.csproj
    del c:Productapp.config
    ren C:Productusertest.config C:Productapp.config
    msbuild /t:publish /p:Configuration=Release;PlatformTarget=x86;UpdateEnabled=true;UpdateMode=Foreground;UpdatePeriodically=false;MinimumRequiredVersion=2013.2.1086.5496;ApplicationVersion=2013.2.1086.5496;UpdateRequired=true;ProductName="User Test Product";InstallUrl="http://usertest.product.temp-uri.org/install/"
    ren C:ProductbinReleaseapp.publish usertest.app.publish
    
    msbuild /t:clean /p:Configuration=Release;PlatformTarget=x86 "C:ProductProduct.csproj
    del c:Productapp.config
    ren C:Productparallelprod.config C:Productapp.config
    msbuild /t:publish /p:Configuration=Release;PlatformTarget=x86;UpdateEnabled=true;UpdateMode=Foreground;UpdatePeriodically=false;MinimumRequiredVersion=2013.2.1086.5496;ApplicationVersion=2013.2.1086.5496;UpdateRequired=true;ProductName="Parallel Prod Product";InstallUrl="http://parallelprod.product.temp-uri.org/install/"
    ren C:ProductbinReleaseapp.publish parallelprod.app.publish
    
    msbuild /t:clean /p:Configuration=Release;PlatformTarget=x86 "C:ProductProduct.csproj
    del c:Productapp.config
    ren C:Productprod.config C:Productapp.config
    msbuild /t:publish /p:Configuration=Release;PlatformTarget=x86;UpdateEnabled=true;UpdateMode=Foreground;UpdatePeriodically=false;MinimumRequiredVersion=2013.2.1086.5496;ApplicationVersion=2013.2.1086.5496;UpdateRequired=true;ProductName="Prod Product";InstallUrl="http://prod.product.temp-uri.org/install/"
    ren C:ProductbinReleaseapp.publish prod.app.publish
    

    The first obstacle I hit was realizing that you must recompile the application if you want to change the config file, version or product name. Simply running a publish after a regular build will not accomplish this task. At this point I figured this would work as each one has a different install URL and a different product name in the application manifest, however they are still conflicting with the same message you are seeing. If I get it working I will come back and update this with the fix.

    链接地址: http://www.djcxy.com/p/22728.html

    上一篇: NetworkX有哪些可扩展性问题?

    下一篇: Clickonce部署到多个环境