We have a desktop Windows app (written in WFP/C#) that we distribute as a single .exe file with no installer (it bundles all its dependencies via a Fody/Costura plugin).
We would like to integrate a local Action Center toast functionality where the app can display a toast and respond to it when it's clicked.
Displaying the toast is straightforward and can be done by using the Microsoft.Toolkit.Uwp.Notifications nuget package. However, in order to actually receive proper notifications when the toast is clicked in the Action Center (as opposed to the balloon tip) we need to register with notification platform.
The guide on how to do this seems to be focused on apps with an installer (e.g. Wix): https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/send-local-toast-desktop?fbclid=IwAR2AoHRKI88VNGRG-pTUytwhkMuovWT4bEr0RoXEayWpWsoGlghtZeq4Mo4#step-4-register-with-notification-platform
The specific task we're trying to achieve is, from the documentation:
If you're using classic Win32 (or if you support both), you have to declare your Application User Model ID (AUMID) and toast activator CLSID (the GUID from step #3) on your app's shortcut in Start.
How can we do it without writing an installer? We would like our app to do this registration on first run.
Note: the app already has provisions for elevating itself through UAC if needed by restarting itself in Administrator context.
Additional references: WPF native windows 10 toasts
[Update]
I managed to follow the instructions in https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/send-local-toast-desktop and https://docs.microsoft.com/en-us/windows/win32/shell/enable-desktop-toast-with-appusermodelid to put together what should have been a working solution, but in the end, clicking on toasts in the Action Center does not trigger OnActivated() in my NotificationActivatior.
Salient points:
Sending notification
var toast = new ToastNotification(toastXml); DesktopNotificationManagerCompat.CreateToastNotifier().Show(toast);Registration:
string shortcutPath = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.Programs), "Toasty.lnk"); DesktopNotificationManagerCompat.RegisterAumidAndComServer <MyNotificationActivator>(AppName); DesktopNotificationManagerCompat.RegisterActivator <MyNotificationActivator>(); if (!File.Exists(shortcutPath)) { ShortcutManager.RegisterAppForNotifications( shortcutPath, Assembly.GetExecutingAssembly().Location, null, AppName, ActivationId); }Creating a shortcut
public static void RegisterAppForNotifications(
string shortcutPath,
string appExecutablePath,
string arguments,
string appName,
string activatorId)
{
var shellLinkClass = new ShellLinkCoClass();
IShellLinkW shellLink = (IShellLinkW)shellLinkClass;
shellLink.SetPath(appExecutablePath);
IPropertyStore propertyStore = (IPropertyStore)shellLinkClass;
IPersistFile persistFile = (IPersistFile)shellLinkClass;
if (arguments != null)
{
shellLink.SetArguments(arguments);
}
// https://docs.microsoft.com/en-us/windows/win32/properties/props-system-appusermodel-id
propertyStore.SetValue(
new PropertyKey("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3", 5),
new PROPVARIANT(appName));
// https://docs.microsoft.com/en-us/windows/win32/properties/props-system-appusermodel-toastactivatorclsid
propertyStore.SetValue(
new PropertyKey("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3", 26),
new PROPVARIANT(new Guid(activatorId)));
propertyStore.Commit();
persistFile.Save(shortcutPath, true);
}
[Update]
Finally got it to work - not sure what was wrong before, but the final version seems to be okay. Full code: https://gist.github.com/davidair/c4ea207bf6eece4ef08b97ab29a3036f