c# - 如何为本地 toast 通知自行注册独立桌面 C# WPF 应用程序(作为 exe 分发)?

标签 c# wpf windows-10

我们有一个桌面 Windows 应用程序(用 WFP/C# 编写),我们将其作为单个 .exe 文件分发,没有安装程序(它通过 Fody/Costura 插件捆绑了所有依赖项)。

我们想集成本地操作中心 toast 功能,应用程序可以在其中显示 toast 并在点击时响应它。

显示 toast 很简单,可以使用 Microsoft.Toolkit.Uwp.Notifications nuget 包来完成。但是,为了在操作中心(而不是气球提示)中单击 toast 时实际收到正确的通知,我们需要注册通知平台。

有关如何执行此操作的指南似乎侧重于带有安装程序(例如 Wix)的应用程序:https://learn.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/send-local-toast-desktop?fbclid=IwAR2AoHRKI88VNGRG-pTUytwhkMuovWT4bEr0RoXEayWpWsoGlghtZeq4Mo4#step-4-register-with-notification-platform

我们试图实现的具体任务是,来自文档:

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.

不写安装程序怎么办?我们希望我们的应用在首次运行时进行注册。

注意:如果需要,该应用程序已经通过 UAC 提升自身,方法是在管理员上下文中重新启动自身。

其他引用资料:WPF native windows 10 toasts

[更新]

我设法按照 https://learn.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/send-local-toast-desktop 中的说明进行操作 和 https://learn.microsoft.com/en-us/windows/win32/shell/enable-desktop-toast-with-appusermodelid将本应有效的解决方案放在一起,但最后,单击操作中心中的 toast 不会触发我的 NotificationActivatior 中的 OnActivated()。

要点:

  1. 发送通知

    var toast = new ToastNotification(toastXml);
    DesktopNotificationManagerCompat.CreateToastNotifier().Show(toast);
    
  2. 注册:

    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);
     }
    
  3. 创建快捷方式

    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://learn.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://learn.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);
    }

[更新]

终于让它工作了 - 不确定之前出了什么问题,但最终版本似乎没问题。完整代码:https://gist.github.com/davidair/c4ea207bf6eece4ef08b97ab29a3036f

最佳答案

我现在的项目也遇到了同样的问题。

设法找到这个存储库 - https://github.com/felixrieseberg/electron-windows-interactive-notifications

这是安装快捷方式的 C++ 实现(InteractiveNotifications 文件,InstallShortcut 方法)。我想问题是我们如何将值设置为 PropertyStore,字符串 GUID 出于某种原因不适合。不过,我暂时无法解决问题。

更新:终于可以从代码安装快捷方式了!在 Github 上查看我的示例。 https://github.com/romayavorskyi/WpfNotificationTest (仍然有很多硬编码,但它应该给你一般的想法)。你是对的,捷径很重要。看来快捷方式应该在 ProgramData 文件夹中才能正常工作。

关于c# - 如何为本地 toast 通知自行注册独立桌面 C# WPF 应用程序(作为 exe 分发)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62490091/

相关文章:

c# - 在 WPF MVVM 应用程序中管理 DbContext

c# - 在 VS2015 的 UWP 解决方案文件夹中创建了奇怪的子文件夹 "DTAR_08E86330_4835_4B5C_9E5A_61F37AE1A077_DTAR"

c# - 如何为scaletransform和rotatetransform设置不同的原点中心?

c# - WPF Prism Bound 字段值在命令触发之前不可用

java - 没有网络就可以更新吗?

c++ - 如何查看 Microsoft Windows 10 的(默认)页面大小?

c# - 使用 asp.net web api 和 knockout js 处理图像上传的输入表单

c# - Webreferences 共享类

c# - 抽象类 MouseAdapter 与接口(interface)

c# - 如何在 C# 打印文档中设置和打印自定义纸张尺寸?