Share via

ClickOnce Deployment – Promoting the Same Tested Build from UAT to Production

Nagarajan Dhanapal 0 Reputation points
2026-06-11T16:03:58.3033333+00:00

We have a .NET application developed using Microsoft ClickOnce technology. The application is digitally signed as part of the release process before being delivered to the client environment.

 

Our client uses uDeploy to manage deployments across environments. Their deployment process requires that the exact same release artifact that was successfully tested in the User Acceptance Testing (UAT) environment be promoted to Production without rebuilding, republishing, or modifying any files. This ensures that the Production deployment is identical to the UAT-tested version and that all file checksums remain unchanged.

 

However, with our current ClickOnce implementation, the environment specific application URL must be embedded during the publish process. As a result, separate ClickOnce releases need to be generated for UAT and Production. This causes the deployment manifests and signed artifacts to differ between environments, resulting in different checksums. Consequently, the Production package is not an exact copy of the UAT tested package, and the client's deployment governance process rejects the release.

 

Could you please advise whether Microsoft provides a recommended approach to support the following requirement: - Build and publish the application only once. - Promote the exact same signed ClickOnce package from UAT to Production. - Avoid environment specific recompilation or republishing. - Allow the application to resolve or obtain the target environment URL at deployment time or runtime without modifying the published ClickOnce artifacts.

Developer technologies | .NET | .NET Runtime

2 answers

Sort by: Most helpful
  1. Danny Nguyen (WICLOUD CORPORATION) 7,105 Reputation points Microsoft External Staff Moderator
    2026-06-12T03:37:14.4966667+00:00

    Hi @Nagarajan Dhanapal ,

    Please check this Microsoft Learn guidance: Deploy ClickOnce apps without re-signing - Visual Studio (Windows).

    ClickOnce can support deploying the same signed application from multiple network locations without re-signing or changing the manifests, by excluding the deploymentProvider from the deployment manifest.

    However, there are some limitations:

    • This is mainly for application updates, not the first installation.
    • It only works when there is one application configuration on the machine.
    • If the manifest or signed package is changed after publishing, it must be re-signed, so the checksum will change.

    So if the UAT/Production URL must be embedded in the ClickOnce manifest, the packages will not be identical. The better direction is to avoid putting environment-specific values inside the signed ClickOnce artifacts and have the application resolve them at runtime, such as from an external configuration endpoint.

    Hope this helps clarify the supported direction. If you need any further help on this, please feel free to reach out.

    If you found my response helpful or informative, I would greatly appreciate it if you could follow this guidance or provide feedback.

    Thank you. 

    Was this answer helpful?

    0 comments No comments

  2. AI answer

    2026-06-11T16:04:20.55+00:00

    Yes. ClickOnce in .NET Framework 3.5 and later explicitly supports this scenario, with some constraints.

    Key points from the platform behavior and guidance:

    1. Single build and publish, reused across environments
      ClickOnce was enhanced so that a third party (the ISV) can create a single signed ClickOnce deployment and then hand it to a customer, who can deploy it from multiple locations on their own network without re-signing or changing the manifests. This is exactly the “build once, deploy to multiple environments” scenario. This feature is intended for:
      • Updating an application (not the very first install), and
      • Situations where only one configuration of the application exists on a given machine (no parallel variants pointing to different backends).
      Deploy ClickOnce applications for testing and production servers without resigning describes this capability.
    2. Do not embed an environment-specific update URL (deploymentProvider)
      The main technical requirement is that the deployment manifest must not contain a deploymentProvider element. In earlier versions (2.0/3.0), an offline-available ClickOnce app had to specify this element, which effectively hard-wired the update location and forced environment-specific manifests. With .NET Framework 3.5 and later, to enable reuse of the same signed package from different locations:
      • Exclude deploymentProvider from the deployment manifest.
      • When using Mage.exe, omit the -providerUrl argument.
      • When using MageUI.exe, leave the Launch Location box blank on the Application Manifest tab.
      This allows the same signed deployment to be copied and hosted at different URLs (for example, UAT and Production) without changing the manifest or re-signing, so the checksums of the ClickOnce artifacts remain identical.
    3. How updates work without deploymentProvider
      When deploymentProvider is omitted, ClickOnce does not rely on a fixed update URL embedded in the manifest. Instead, the deployment is tied to the location from which it was originally installed. The customer can host the same artifact in different locations (e.g., a UAT URL and a Production URL) and install from each location as needed, without modifying the manifests.
    4. Environment selection at deployment/runtime
      ClickOnce itself does not provide a built-in mechanism to dynamically choose an environment URL at install time while keeping a single installed instance per machine. The supported pattern for “build once, deploy many” is:
      • Build and sign once.
      • Omit deploymentProvider so the same package can be hosted and deployed from multiple locations.
      • Ensure that each client machine only runs one configuration of the app (for example, not both a UAT and Production variant with different backends) if relying on this feature.
      Environment-specific behavior (such as which backend URL to call) is typically handled by the application at runtime (for example, via configuration or service discovery) rather than by changing ClickOnce artifacts.
    5. Security and signing considerations
      The identity of a ClickOnce application is based on the digital signature of the deployment manifest. When a single ISV-signed deployment is reused by a customer across environments, that identity and trust chain remain intact, and the customer does not need to re-sign the deployment manifest, avoiding checksum changes. For scenarios where customers must sign their own deployment manifests, Microsoft also documents the alternative model where the ISV signs the application manifest and the customer signs the deployment manifest, but that model does require re-signing and therefore changes checksums.

    Summary relative to the stated requirements:

    • Build and publish only once: Supported by creating a ClickOnce deployment that omits deploymentProvider and is signed once.
    • Promote the exact same signed package from UAT to Production: Supported; the same signed deployment can be copied/hosted in multiple locations without modification or re-signing.
    • Avoid environment-specific recompilation/republishing: Supported; no rebuild or republish is required when moving from UAT to Production.
    • Resolve environment URL at deployment/runtime without modifying artifacts: Supported in the sense that ClickOnce does not need an environment-specific deploymentProvider; environment-specific behavior should be handled by the application logic or by where the deployment is hosted, not by changing the ClickOnce manifests.

    References:

    AI-generated content may be incorrect. Read our transparency notes for more information.

    Was this answer helpful?

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.