Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ClickOnce Support for .NET Core #9

Closed
nakarnam opened this issue Jul 20, 2020 · 36 comments
Closed

ClickOnce Support for .NET Core #9

nakarnam opened this issue Jul 20, 2020 · 36 comments
Assignees

Comments

@nakarnam
Copy link

nakarnam commented Jul 20, 2020

Objective

Provide ClickOnce Support for .NET Core apps in the .NET 5 timeframe i.e. the ability for .NET Core apps to auto update on launch. This brings functional parity across most of the ClickOnce scenarios for the developer community, particularly those in Enterprise/Line of business.

High level User Experience and Scope

Developer experience includes an updated integrated publish experience in VS with ClickOnce as a new provider option, a new open sourced Mage tool for enabling the command line experience for manifest generation and updated MSBuild tasks to support the changes required in VS and Mage for .NET Core Projects.

At a high level, the proposal is to use a .NET Framework based launcher application, transparent to the user and responsible for activating the .NET Core app specified in the launcher’s config/manifest file. There are no changes expected to the OS components that ClickOnce Runtime relies on, such as Dfshim, DFSVS etc.

Please note that ClickOnce ApplicationDeployment class and its APIs will not be available for use by .NET Core applications. For example, downloading assemblies at will and Custom hosting – InPlaceHostingManager scenarios are not supported. Also, scope does not include support for in-app updates or updates upon app close since the launcher app closes once the .NET Core app is activated. Partial trust is not a supported feature in .NET Core, therefore not in scope.

Windows 7 is not a supported platform. However, Win 7 users with .NET 4.5.2+ will not be blocked from using ClickOnce for deploying .NET Core apps.

@billybednar
Copy link

Please note that ClickOnce ApplicationDeployment class and its APIs will not be available for use by .NET Core applications.

That's a bit disappointing. The standard update check has behavior that's problematic in our environment (silently continuing if the update check failed) and we use the CheckForUpdate API to supplement it. We just need the boolean result (or exception) and don't actually need to trigger the update. If it's not possible to include at least a subset of the ApplicationDeployment class, perhaps there could be a way to specify a custom launcher application.

What about URL parameters, specifically for file associations? The launcher could translate AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData into command line arguments.

@NikolaMilosavljevic
Copy link
Member

Please note that ClickOnce ApplicationDeployment class and its APIs will not be available for use by .NET Core applications.

That's a bit disappointing. The standard update check has behavior that's problematic in our environment (silently continuing if the update check failed) and we use the CheckForUpdate API to supplement it. We just need the boolean result (or exception) and don't actually need to trigger the update. If it's not possible to include at least a subset of the ApplicationDeployment class, perhaps there could be a way to specify a custom launcher application.

What about URL parameters, specifically for file associations? The launcher could translate AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData into command line arguments.

We are tracking work to add support for URL parameters.

I understand that failure in update check, before app launch seems to be ignored today. @billybednar what are the common reasons for failures in update check in you environment?

@billybednar
Copy link

I understand that failure in update check, before app launch seems to be ignored today. @billybednar what are the common reasons for failures in update check in you environment?

Server issues, not being connected to the network, and the deployment being deleted. The first two typically aren't a big deal since they're temporary, but in some cases a warning or other action is desirable. The removal of deployments, typically betas, is our real problem because it leaves behind installations that appear to be getting updates but aren't really. The ApplicationDeployment class allows us to detect an update failure, classify it as temporary or permanent, and provide a response appropriate for the application.

@NikolaMilosavljevic
Copy link
Member

NikolaMilosavljevic commented Aug 21, 2020

The removal of deployments, typically betas, is our real problem because it leaves behind installations that appear to be getting updates but aren't really. The ApplicationDeployment class allows us to detect an update failure, classify it as temporary or permanent, and provide a response appropriate for the application.

I see - you are doing silent updates. ApplicationDeployment class is not available in .NET (Core). But, Launcher could do the update check and, in some way, communicate the result to the application. We'll take a look at this and come up with the solution - I've created an issue for this: #27

@wjk
Copy link

wjk commented Aug 26, 2020

One question, although I don't think it would be possible to achieve in the near future. As I understand it, ClickOnce installations always prompt the user to click a button during removal, with no way to suppress it. This has resulted in projects like this one needing to exist. Is there any way we could work around this? This issue precludes being able to uninstall ClickOnce-packaged applications using automated scripts in mass deployments. (I don't think it precludes inclusion in winget, however, as winget does not yet offer the feature of completely silent removals AFAICT.) Thanks!

@NikolaMilosavljevic
Copy link
Member

@wjk unfortunately there is no way to uninstall applications silently without writing a custom application to wrap uninstallation process and send keys to accept the dialog prompt. Project you linked works differently and imitates ClickOnce uninstall actions by deleting files and registry keys. I have not investigated it closely and cannot endorse it.

@wjk
Copy link

wjk commented Aug 26, 2020

@NikolaMilosavljevic That's fine. Just wanted to throw it out there. Besides, I always install my apps with /passive rather than /quiet, so I’m used to dealing with popups. 😄 Thanks anyway!

@mansellan
Copy link

mansellan commented Aug 27, 2020

I recently wrote an open-source project to do this, with a very similar modus operandi - when a net core executable is detected, it creates a netfx launcher (albeit without any finesse wrt parameters). I also wrapped it as an Azure DevOps pipeline task.

In doing so, I noticed the following which might apply to this effort:

  • If strong-named .Net Core assemblies are marked as assemblies, the ClickOnce runtime will reject them with a signature failure. If they are marked as files, the build API will warn, but the runtime accepts them. My company is using this workaround right now to deploy a Net Core application which includes some strong-named assemblies over ClickOnce. Net Core assemblies that are not strong-named can be marked as assemblies without problem.
  • If a Net Core executable includes an embedded manifest, it will be rejected by the ClickOnce runtime.(1)
  • Reg Free COM and File Associations are difficult to accomodate.
  • In theory, if you're going to allow Net Core executables to be launched, there's no extra effort in allowing any executable to be launched.
  • If you're going to allow the launcher to accept URL parameters, please consider allowing them to accept command-line parameters as well. I appreciated why these were excluded at the time, but it would now be extremely useful to permit them (e.g. to tie into the Net Core config pipeline for CI)

(1) In Visual Studio under the old project system for net fx, if a project includes a manifest, it will be intercepted by the ClickOnce publish pipeline. Instead of being embedded (regardless of project setting), it will be intercepted and merged with the external ClickOnce manifest being created. As I was working with compiled binaries, this was a problem - I would have to detect it in the binary, extract it, modify the binary and then merge it with the external manifest. I elected to avoid the issue by mandating that executables must not have an embedded manifest.

@mansellan
Copy link

I would also agree with @billybednar that the "silent fail" update that ClickOnce ships with is unsatisfactory. We've had to write bespoke telemetry to even notice it, and will likely need to come up with enforcement strategies soon.

@NikolaMilosavljevic
Copy link
Member

@mansellan your solution looks great! You are right in all of the points you bring, we have encountered all of them and made decisions to, for instance, do simple-file dependencies and modify MSBuild task to not warn for Core apps. We will also require executable to not have an embedded manifest, that is simply the requirement imposed by ClickOnce runtime. We will be working soon on update, check and failure, improvements, adding support for URL parameters and bringing Mage tool into this repo.

@RealDotNetDave
Copy link

I have asked for this too. Let me know if you need any help with testing or ideas!

David McCarter

@EdwinEngelen
Copy link

EdwinEngelen commented Oct 2, 2020

Please note that ClickOnce ApplicationDeployment class and its APIs will not be available...

We are tracking work to add support for URL parameters.

Just wondering whether you've got us covered regarding our migration to .NET 5 with ClickOnce.

In .NET Framework we use the properties ApplicationDeployment.IsNetworkDeployed and ApplicationDeployment.ActivationUri (includes uri parameters). Two essestial properties in our opinion, because otherwise you can't figure out the address of the server.

Will this information be available (via other interface)?

@NikolaMilosavljevic
Copy link
Member

Please note that ClickOnce ApplicationDeployment class and its APIs will not be available...

We are tracking work to add support for URL parameters.

Just wondering whether you've got us covered regarding our migration to .NET 5 with ClickOnce.

In .NET Framework we use the properties ApplicationDeployment.IsNetworkDeployed and ApplicationDeployment.ActivationUri (includes uri parameters). Two essestial properties in our opinion, because otherwise you can't figure out the address of the server.

Will this information be available (via other interface)?

Since .NET (Core) doesn't implement ApplicationDeployment, there is no way to do update check or perform the update from the application. Usability of ApplicationDeployment properties is much lower, but I can see the value in obtaining and exposing ActivationUri property.

We are working on a design to add some of this missing functionality to Launcher (as it is a .NET FX app). We planned for doing update check to determine if update location is reachable. We could also grab ActivationUri value. Launcher would create a json file in application folder to expose this, ClickOnce deployment, data. A PR for this will be coming in the next couple of weeks.

@NikolaMilosavljevic
Copy link
Member

Closing this issue as the feature is complete: https://devblogs.microsoft.com/dotnet/announcing-net-5-0-rc-2

Thank you for all your input. We look forward to more input as issues in this repo.

@mihaimyh
Copy link

I see this issue was closed, do we got something implemented in .NET5?

@MichaelSimons
Copy link
Member

@mihaimyh - yes, please see the 5.0 RC2 blog for a summary.

@NikolaMilosavljevic
Copy link
Member

@mihaimyh we are working on documentation, for final release. At the moment we have some small docs for command-line experience at: https://github.com/dotnet/deployment-tools/tree/master/Documentation/dotnet-mage

@mihaimyh
Copy link

@mihaimyh we are working on documentation, for final release. At the moment we have some small docs for command-line experience at: https://github.com/dotnet/deployment-tools/tree/master/Documentation/dotnet-mage

Thank you, I will look into it.

@farhadmammadli
Copy link

@NikolaMilosavljevic I tried to migrate from dotnet framework 4 to dotnet core 3.1 or v5, but still cannot use
ApplicationDeployment class. Tried to install preview version of VS, still not found. How can I use it?

I am using WPF and installed dotnet 5.0

@NikolaMilosavljevic
Copy link
Member

@farhadmammadli ApplicationDeployment class is not available - that class is implemented in System.Deployment assembly that is not part of .NET Core 3.1 or .NET 5.

We will have a way to expose some of the properties that the class enables, i.e. URL parameters and update status. But, that work could not be completed for .NET 5 release. We will enable it in one of .NET 6 previews. Here are the tracking issues: #27 and #53

@raffaeler
Copy link

@NikolaMilosavljevic If this is not yet available, can you explain the current supported scenario?
I can't see how to migrate certain WPF applications that are currently deployed using .NET Framework with ClickOnce.

@NikolaMilosavljevic
Copy link
Member

@raffaeler Use of ApplicationDeployment class in your deployed ClickOnce application is not possible, but main ClickOnce experience is available. It includes: creating ClickOnce deployment (manifests), publishing the application, creating and publishing updates. Your application will get automatic update check (and update, if user accepts it) - this part is handled by ClickOnce runtime and the new Launcher tool that becomes the entry point of ClickOnce deployment for .NET Core 3.1 and .NET 5 applications.

Are you using CLI (dotnet-mage) or Visual Studio 16.8?

Extensive documentation will be available in the near future, but we have some initial docs for dotnet-mage at: https://github.com/dotnet/deployment-tools/tree/release/5.0/Documentation/dotnet-mage

@raffaeler
Copy link

I am using VS and didn't try to port any app just because they were missing ClickOnce and ApplicationDeployment that we heavily used for many apps.
I am not sure whether it can be wise for us to undo the code supporting ApplicationDeployment or just wait.

For sure I would be more comfortable in waiting an update not tied to .NET vNext.

@NikolaMilosavljevic
Copy link
Member

I am using VS and didn't try to port any app just because they were missing ClickOnce and ApplicationDeployment that we heavily used for many apps.
I am not sure whether it can be wise for us to undo the code supporting ApplicationDeployment or just wait.

Which methods and properties from ApplicationDeployment class are mostly used in your apps? Is it primarily for on-demand update check?

For sure I would be more comfortable in waiting an update not tied to .NET vNext.

Previews of dotnet-mage and VS would bring new features and fixes throughout the year and will not be tied to final build of .NET 6.

However, I would suggest, if at all possible, trying to convert some of those apps, early. It would help discover the missing scenarios, which we can discuss in these issues and make plans for fixes and new features.

@raffaeler
Copy link

These are the members that are very used from most of the apps:

  • CurrentDeployment
  • CheckForUpdateCompleted
  • CheckForUpdateAsync
  • UpdateCompleted
  • UpdateAsync
  • IsNetworkDeployed
  • CurrentVersion
    and
  • CheckForUpdateCompletedEventArgs

I would start to migrate those apps, but we could not get rid of the ApplicationDeployment. Users are already used to rely on that behavior.

@NikolaMilosavljevic
Copy link
Member

Thanks! These all seem related to on-demand update, during application runtime. Are your applications long running, or relaunched semi-frequently, i.e. every day? How often is an update deployed, on average?

One option, perhaps simplistic, would be to initiate application restart, which would cause automatic check for update and prompt for installation, if one is available. Using today's on-demand update your application would also need to be restarted to apply the update. Granted, there is no update for just the update check.

@raffaeler
Copy link

It depends on the applications. Mostly they are run once per day but some of them may require to be restarted because of changes on the server side (services).
I can't rely just on restarting the app because we have a UI for telling the users whether they want to continue, update or roll-back.
BTW rollback is important because sometimes the changes do not work well for them.

@NikolaMilosavljevic
Copy link
Member

@raffaeler there are several ways to invoke rollback from your application - which one do you use? It would help us solidify the requirements for this feature.

@raffaeler
Copy link

@NikolaMilosavljevic currently the user redirected to the internal website where the apps are published and he/she is free to install any previous releases. In case of breaking changes not compatible with the server side, the incompatible version will advise the user that the version is too old. Not a perfect solution, but very easy and understandable for the user.
The point here is that the website is a central repository with all the available versions.
Starting from this baseline, anything should work nicely.

@sunchar
Copy link

sunchar commented Jun 10, 2021

Hi!

I don't know if this is the right place for asking this.

I modified my legacy .csproj files to SDK-Style on a .NET Frameworrk 4.8 projects, everything is working fine, but i cannot publish Clickonce, Visual Studio doesn´t give me any other option than publish to a folder as shown in picture.

Please, advise how to publish clickonce with SDK-Style .csproj files.

Thank you!

image

@NikolaMilosavljevic
Copy link
Member

Hi!

I don't know if this is the right place for asking this.

I modified my legacy .csproj files to SDK-Style on a .NET Frameworrk 4.8 projects, everything is working fine, but i cannot publish Clickonce, Visual Studio doesn´t give me any other option than publish to a folder as shown in picture.

Please, advise how to publish clickonce with SDK-Style .csproj files.

Thank you!

cc @John-Hart

@John-Hart
Copy link

Unfortunately, we do not support .NET Framework SDK style projects with ClickOnce in Visual Studio. I recommend using Mage (see https://docs.microsoft.com/en-us/dotnet/framework/tools/mage-exe-manifest-generation-and-editing-tool)

@sunchar
Copy link

sunchar commented Jun 10, 2021

Bad news.

Thanks!

@amselem
Copy link

amselem commented Jun 12, 2021

I was also hoping to have Clickonce support in .Net Framework SDK style projects. Is this planned for the future release of .Net 6 ?

@ckschiefer
Copy link

Recently discovered that a .NET Core application must be signed with a strong name in order for ClickOnce updates to properly pull forward user settings. This was not necessary for ClickOnce FX. Why is this needed for ClickOnce for .NET Core?

Strong-named assemblies

For .NET Core and .NET 5+, strong-named assemblies do not provide material benefits. The runtime never validates the strong-name signature, nor does it use the strong-name for assembly binding.

@paulpv
Copy link

paulpv commented Sep 26, 2024

https://learn.microsoft.com/en-us/visualstudio/deployment/access-clickonce-deployment-properties-dotnet

Starting in .NET 7 and Visual Studio 2022 version 17.4, you can access ClickOnce deployment properties by using an environment variable.

The application launcher shares ClickOnce application deployment properties with the application being launched (.NET only). Properties are shared with the application by using environment variables.

The variable names closely match the properties in the .NET Framework ApplicationDeployment class. The new variable names include a ClickOnce_ prefix:

ClickOnce_IsNetworkDeployed
ClickOnce_ActivationUri
ClickOnce_CurrentVersion
ClickOnce_DataDirectory
ClickOnce_IsFirstRun
ClickOnce_TimeOfLastUpdateCheck
ClickOnce_UpdatedApplicationFullName
ClickOnce_UpdatedVersion
ClickOnce_UpdateLocation
In addition to these changes, a new property is available that returns the application launcher version:

ClickOnce_LauncherVersion
A .NET application can use these properties directly or indirectly.

Note

Using this method, you can access application deployment properties, but .NET 7 does not support the equivalent of ApplicationDeployment methods.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests