deployment-tools
deployment-tools copied to clipboard
Pinned taskbar app is orphaned after update
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?
Investigating.
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.
Do you have any update on when this issue will be resolved?
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<username>\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<username>\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.
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
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
.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.
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.
Does this work fine for .NET FX apps? Have you tried to enable shortcut creation for ClickOnce deployment?
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?
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.
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.
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.
@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.
@billybednar - thanks a lot for the suggestions, it looks like it works.
To wrap up:
- i created a custom launcher.exe where i call
GetCurrentProcessExplicitAppUserModelID
and pass the app user model id to my application as a process scoped environment variable (e.g.:CLICKONCE_APPUSERMODELID
). - in my application if i can read the
CLICKONCE_APPUSERMODELID
, i set my app's app user model id to the same value usingSetCurrentProcessExplicitAppUserModelID
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).
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.
Hi all. Is the expectation that this is a .NET 7.0 fix or before then?
@billybednar, would you be willing to share your fix?
Hi @NikolaMilosavljevic, is this fix likely to ship with .NET 7.0?
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.
Thanks!
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 😆
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.
@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, 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 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.
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.
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.
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.
Will this be fixed and released along with dotnet mage 7.0?