dotnet / deployment-tools

This repo contains the code to build the .NET deployment tools and installers for all supported platforms, as well as the sources to .NET deployment tools.
MIT License
172 stars 52 forks source link

Pinned taskbar app is orphaned after update #74

Open desjarlais opened 3 years ago

desjarlais commented 3 years ago

Scenario: I publish a .NET 5 app using ClickOnce and then pin the app to the Windows taskbar. After pinning to the taskbar, if I update the app, it will be orphaned to the old version. The Start Menu app icon works fine after the update, it just seems to be the taskbar. Is there any way to work around having to unpin/repin the app icon post update?

NikolaMilosavljevic commented 3 years ago

Investigating.

desjarlais commented 3 years ago

This seemed to be working after installing VS 16.9.4, but that isn't the case anymore. For some reason the first update I pushed through ClickOnce seemed fine, but the next update after that, the issue came back.

ckorlinchak commented 3 years ago

Do you have any update on when this issue will be resolved?

desjarlais commented 3 years ago

I'm not sure what the current plan or status is for this, but I'm currently using a workaround of comparing the target of the shortcut with the current executing assembly path of my app.

The location of the pinned app is: C:\Users\\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\<appname.lnk

The target of that particular shortcut .lnk file is something like this: C:\Users\\AppData\Local\Apps\2.0\1LZPH5VH.RQ0\GQ7Z7W3A.ADA\<abbreviated app folder name + long guid like value>\appname.exe

Not sure if there is a better way to do it, but I use Shell32 to pull the target location for comparison and then change that if they are different. Seems to work so far, but there is some extra work to make sure I'm not changing during debug mode.

simmotech commented 3 years ago

Not sure if you guys already knew this but there seems to be a difference in how the pinning is done. If you right-click the desktop icon and pin it that way, it runs and updates fine. If you run the application first then right-click to pin it from the taskbar then it always runs directly and bypasses update checking.

You can check the Properties/Details to compare - the former is a .appref-ms and the latter is a .lnk

e-master commented 2 years ago

Indeed, i got the same issue. The crux of the problem is that in .NET (core) the application is separate from the launcher (Launcher.exe).

To work around this problem i plan to add the following logic into my application:

NikolaMilosavljevic commented 2 years ago

.appref-ms is the proper link and should be pinned. Pinning a running application would pin a link to app exe - subsequent runs would not go through ClickOnce.

e-master commented 2 years ago

Fully agree. Except as of now it is impossible for users to pin .appref-ms when they right-click on a running .NET 5/6 ClickOnce app in the task bar and select Pin to taskbar. That's why i suggested to do an ugly workaround above.

NikolaMilosavljevic commented 2 years ago

Does this work fine for .NET FX apps? Have you tried to enable shortcut creation for ClickOnce deployment?

e-master commented 2 years ago

yes, i have the exact same app (multi-targeted to .net 4.5.2 and .net 5) and the .net 4.5.2 deployment can be pinned properly, but the .net 5 one cannot (well, links the local .exe instead).

Have you tried to enable shortcut creation for ClickOnce deployment?

I'm not sure exactly what you mean. I can see that both .net 4.5.2 and .net 5 create a shortcut in the Start menu, but i don't see anything shortcut related in my ClickOnceProfile.pubxml file, so i assume shortcut creation is on by default? Or perhaps is there some flag i can turn on in the .pubxml file?

e-master commented 2 years ago

i assume you talked about the CreateDesktopShortcut flag. No, i don't use that in my .pubxml file. Do you think that would fix this issue? I can give it a try.

billybednar commented 2 years ago

Indeed, i got the same issue. The crux of the problem is that in .NET (core) the application is separate from the launcher (Launcher.exe).

To work around this problem i plan to add the following logic into my application:

  • at every startup/shutdown check if the user has a *.lnk file to my application in the %appdata%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar folder
  • if they do, it means they created the "wrong" link to my app, because that link points to the local copy of the application
  • copy my app's proper link file from %appdata%\Microsoft\Windows\Start Menu\Programs...*.appref-ms into the %appdata%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar folder and remove the useless *.lnk file

I'd be quite surprised if that worked. Pinning something to the taskbar is intentionally difficult to prevent abuse.

When you pin a .NET Framework ClickOnce application to the taskbar, the apprefms is pinned rather than the executable because ClickOnce somehow sets the same explicit AppUserModelID on the process that it starts (the .NET Framework in the target is probably cooperating). With .NET 5+, this isn't getting done because ClickOnce is starting the launcher rather than your application. You can test this by retrieving the AUMID of the current install of some ClickOnce application (IIRC it changes on each install or upgrade) and making a totally separate non-ClickOnce application that calls SetCurrentProcessExplicitAppUserModelID with that value. If you pin the test application, the pin will start the ClickOnce application instead of the test application.

I'm not sure how you can retrieve the correct AUMID at runtime from within your application. The most straightforward way to workaround the various ClickOnce issues is probably to use a custom launcher. It can call GetCurrentProcessExplicitAppUserModelID and pass it along to your application.

e-master commented 2 years ago

I'd be quite surprised if that worked. Pinning something to the taskbar is intentionally difficult to prevent abuse.

You're right, simply moving the files around doesn't work, as designed by the system itself to prevent abuse.

I still found a workaround though. Currently the system creates a .lnk file when the user pins the clickonce application to the taskbar. Although i cannot (easily) programmatically pin/unpin the .appref-ms file, i can change the target of the .lnk file to point to the .appref-ms file. Just tested it manually, seems to work, can't see why it wouldn't work programmatically, but will test it next week.

@NikolaMilosavljevic - i tried with <CreateDesktopShortcut>True</CreateDesktopShortcut>. With that option my deployment created a shortcut for my application on the desktop. When i right-click on the desktop shortcut and select Pin to taskbar it works as expected, however it doesn't solve my original problem - users more often than not right-click on the running application in the task bar and pin right there, instead of finding the icon on the desktop/start menu. In this latter case pinning doesn't work, and i need to revert to the only ugly hack i could find so far described above.

e-master commented 2 years ago

@billybednar

I'm not sure how you can retrieve the correct AUMID at runtime from within your application. The most straightforward way to workaround the various ClickOnce issues is probably to use a custom launcher. It can call GetCurrentProcessExplicitAppUserModelID and pass it along to your application.

Thanks for the suggestions. I will have to create a custom launcher anyways because of this bug https://github.com/dotnet/deployment-tools/issues/53, so i might as well try your suggestion.

e-master commented 2 years ago

@billybednar - thanks a lot for the suggestions, it looks like it works.

To wrap up:

Preliminary testing shows that it works perfectly. Finally the pinned icon is pointing to the .appref-ms, and it even works after application updates.

@NikolaMilosavljevic, I'd be happy to submit a PR, but so far there's no 'official' way of passing information from the launcher to the application (last time i tried to use process scoped environment variables to do that my PR #135 was rejected).

NikolaMilosavljevic commented 2 years ago

Thanks @billybednar and @e-master - I did plan to experiment with GetCurrentProcessExplicitAppUserModelID and it seems that the model is working, that's great! No hard dates on timeline for updates in official Launcher, but it is certainly coming soon.

SartorialOffense commented 2 years ago

Hi all. Is the expectation that this is a .NET 7.0 fix or before then?

SartorialOffense commented 2 years ago

@billybednar, would you be willing to share your fix?

SartorialOffense commented 2 years ago

Hi @NikolaMilosavljevic, is this fix likely to ship with .NET 7.0?

NikolaMilosavljevic commented 2 years ago

The fix for this issue is likely localized to dotnet-mage tooling which ships on its own schedule. We do try to align with major .NET releases, i.e. 7.0 GA.

We're still tracking this issue for investigation and fix for 7.0.

SartorialOffense commented 2 years ago

Thanks!

znakeeye commented 2 years ago

I suppose 7.0.0-preview.2.22317.2 does not solve this issue? When can we expect a release (or preview release) that fixes this problem?

We are currently facing this problem, and we need a fix like... yesterday 😆

NikolaMilosavljevic commented 2 years ago

I've investigated this issue and feel that the best option is to have Launcher set its own custom AppUserModel ID. Windows generates and assigns an ID to apps, but that value cannot be obtained using GetCurrentProcessExplicitAppUserModelID API.

Furthermore, once we have custom AppUserModel ID for Launcher, we should pass it to child process (.NET app), so it gets automatically assigned and not require any work on the app side.

To enable all this, we'd need to switch from using Process and ProcessStartInfo classes and use CreateProcess API. It's a bigger change than anticipated, but it will bring the best overall experience.

Still on 7.0 release timeline, just not ready for implementation or preview yet.

In the meantime, we'd like to get your opinion on alternative way of pinning apps to Taskbar, from Start Menu. It seems to work, but it does have a small side-effect of new icon (for .NET app) appearing in Taskbar, while the app is running.

SartorialOffense commented 2 years ago

@NikolaMilosavljevic Very exciting, it would be great to have it fixed this year.

For the alternative way, do you mean having my users pin the app to the Taskbar from the shortcut on the Start Menu? We try and have them do this now and it does work - we don't see the double icons. Or do you mean something else? I have seen this with Java applications and it is a little confusing.

billybednar commented 2 years ago

@billybednar, would you be willing to share your fix?

See e-master's summary above. Unfortunately I don't have any code handy that I can share, but it only takes a few lines to implement it. The hard part is probably getting the tooling to package up both your application and your launcher in a clean way. I've only done it the quick-and-dirty way as a proof of concept by creating a .NET Framework project as a launcher, pasting the compiled test application into it, adding a few lines of code to start the test application, and publishing the launcher project from within Visual Studio.

I've investigated this issue and feel that the best option is to have Launcher set its own custom AppUserModel ID. Windows generates and assigns an ID to apps, but that value cannot be obtained using GetCurrentProcessExplicitAppUserModelID API.

In my experience, the application started by ClickOnce always uses an explicit ID set by ClickOnce and not the system generated one. I have some .NET Framework WinForms applications that use GetCurrentProcessExplicitAppUserModelID and it returns a value when the application is deployed with ClickOnce and nothing when run standalone. Have you found otherwise?

Edit: According to this (last bullet), ClickOnce does assign explicit IDs:

An example of this situation is the ClickOnce framework, which properly assigns AppUserModelIDs on behalf of the applications that it manages.

NikolaMilosavljevic commented 2 years ago

@NikolaMilosavljevic Very exciting, it would be great to have it fixed this year.

For the alternative way, do you mean having my users pin the app to the Taskbar from the shortcut on the Start Menu? We try and have them do this now and it does work - we don't see the double icons. Or do you mean something else? I have seen this with Java applications and it is a little confusing.

Yes, that's the same workaround, which seems to work fine. I was getting a second icon, in my quick test.

NikolaMilosavljevic commented 2 years ago

In my experience, the application started by ClickOnce always uses an explicit ID set by ClickOnce and not the system generated one. I have some .NET Framework WinForms applications that use GetCurrentProcessExplicitAppUserModelID and it returns a value when the application is deployed with ClickOnce and nothing when run standalone. Have you found otherwise?

Edit: According to this (last bullet), ClickOnce does assign explicit IDs:

An example of this situation is the ClickOnce framework, which properly assigns AppUserModelIDs on behalf of the applications that it manages.

Hmm, that's interesting as it did not work in my tests, on Windows 11. Thank you for sharing the pointer, I will follow up with ClickOnce runtime team if needed.

billybednar commented 2 years ago

Hmm, that's interesting as it did not work in my tests, on Windows 11.

That's strange. It has worked for me on Windows 7 and 10, but I've never tried 11.

NikolaMilosavljevic commented 2 years ago

Hmm, that's interesting as it did not work in my tests, on Windows 11.

That's strange. It has worked for me on Windows 7 and 10, but I've never tried 11.

Yeah, I just double-checked - it works fine on Windows 11, as well.

SwedishBobby commented 2 years ago

Will this be fixed and released along with dotnet mage 7.0?

NikolaMilosavljevic commented 2 years ago

Will this be fixed and released along with dotnet mage 7.0?

Not with GA release, but soon after with a first or second servicing update - December/January timeframe.

maxbanas commented 1 year ago

Does this work fine for .NET FX apps? Have you tried to enable shortcut creation for ClickOnce deployment?

It works except if you pin the app when it was opened following an install or update (I've tested this in .NET Framework 3.5 and 4.8.). For some reason in Framework the AppUserModelID is null right after the install/update, but it will have a value if you run it normally from a appref-ms. So my workaround is to check AppUserModelID using GetCurrentProcessExplicitAppUserModelID and then just restart the application if it's null.

This doesn't seem to work for me in .NET 6+ though, I always get null from GetCurrentProcessExplicitAppUserModelID.

SartorialOffense commented 1 year ago

Just wanted to check in and see if this was still on the horizon for early 2023? Thanks!

NikolaMilosavljevic commented 1 year ago

Just wanted to check in and see if this was still on the horizon for early 2023? Thanks!

Yes, it is. We have just released Preview 1 with one of the other requested features: https://github.com/dotnet/deployment-tools/issues/254

SartorialOffense commented 1 year ago

Excellent! So if I understand correctly, I will need to wait until .NET 8.0 ships before this works using the normal VS ClickOnce publish process. Until then, I can manually build deployments in the CLI with mage.

Is this correct?

NikolaMilosavljevic commented 1 year ago

Excellent! So if I understand correctly, I will need to wait until .NET 8.0 ships before this works using the normal VS ClickOnce publish process. Until then, I can manually build deployments in the CLI with mage.

Is this correct?

The other feature, I mentioned, is available in CLI (dotnet-mage) right now, fix for apps pinned to taskbar is coming in the near future.

@John-Hart do you know when new Launcher will be available in public VS builds?

mario-mantese commented 1 year ago

.NET 8 is coming Any updates on this issue?

SartorialOffense commented 1 year ago

@NikolaMilosavljevic Does it look like this will get fixed in 8.0? I get nervous with the RC out and I don't see this issue marked as completed.

softandbyte commented 1 year ago

Issue still exists in Net 8.0 (rc2.0) ( see screenshot = pinned via running context and pinned via start menu ) image

sra-michaelgold commented 1 year ago

@NikolaMilosavljevic - please provide an update on this. Did this fix make it into Net 8? If not, will it be coming in an update prior to potentially Net 9?

Thank you for your help

SartorialOffense commented 10 months ago

Is it possible to get an update on this? I know there are a lot of competing priorities and never enough time for everything, but this was broken in 2020 and targeted for 7.0 and then 8.0, and now...

MrFJ commented 9 months ago

Still facing this issue as well. I need to be able to "force" updates on my users...

nuzolx commented 8 months ago

@NikolaMilosavljevic @John-Hart @joeloff @sujitnayak

Please, do you have any update with this issue?

MarcelloPoletti commented 8 months ago

This issue has been open for years and is extremely annoying. Can it be prioritized?

TimKras commented 7 months ago

Excellent! So if I understand correctly, I will need to wait until .NET 8.0 ships before this works using the normal VS ClickOnce publish process. Until then, I can manually build deployments in the CLI with mage. Is this correct?

The other feature, I mentioned, is available in CLI (dotnet-mage) right now, fix for apps pinned to taskbar is coming in the near future.

@NikolaMilosavljevic Do you have an update on this one?

rossvegas commented 7 months ago

I would also like to see this happen. I went through the trouble of porting my WPF app from .NET (framework) to .NET (core) a couple of years ago only to be disappointed right at the finish line by this issue.

I am still running under framework because it still works fine but I am missing out on the improvements in .NET (core) and am tied to .NET Standard 2.0 for interoperability. I am also missing out on C# language features that are not supported by .NET Standard 2.0

CD pipelines are also more complicated because I have this one framework project that needs to be handled differently.

mfrisch-rts commented 6 months ago

Looking for an update on this as well.

mario-mantese commented 5 months ago

Is this issue still being worked on? Any info would be appreciated

ESharpAB commented 5 months ago

I would really need this fixed as well. Please update the thread with the current plan. Thanks,/Daniel

JimVidner commented 5 months ago

This is really annoying bug. We have a client-server application and we need the client side to be updated regurarly. When it isn't it fails to work and our client service needs to explain to our clients that they cannot pin the application running and that we are not able to do anything about it. Is there any timeframe, when it can be fixed?