是否可以从控制台应用程序发送 Toast 通知?
Posted
技术标签:
【中文标题】是否可以从控制台应用程序发送 Toast 通知?【英文标题】:Is it possible to send Toast notification from console application? 【发布时间】:2016-10-29 22:51:51 【问题描述】:是否可以使用 ToastNotificationManager 从控制台应用程序发送 Toast 通知?
我知道可以从 Windows 通用应用程序发送 Toast 通知:
var toast = new ToastNotification(doc);
ToastNotificationManager.CreateToastNotifier().Show(toast);
*doc - Toast 存储在 XML 字符串中
要使用 ToastNotificaionManager,我需要在控制台应用程序项目中无法引用的 Windows.UI.Notifications 库。
我之前提到的库实际上是由 WinRT 使用的。是否可以在 Windows 控制台应用程序中使用 WinRT API?
【问题讨论】:
控制台应用程序没有 GUI,因此 Toast 没有意义,不是吗? 干杯什么?您似乎已经回答了自己的问题。 Notifications 有很多应用,在这种情况下我真的很需要它 控制台应用程序应该在后台运行并在事件发生时发送通知 ***.com/questions/12745703/… 可能就是你要找的东西 【参考方案1】:首先您需要声明您的程序将使用 winRT 库:
-
右键单击您的项目,选择卸载项目
右键单击 yourProject(不可用),然后单击 Edit yourProject.csproj
添加新的属性组:
<targetplatformversion>8.0</targetplatformversion>
重新加载项目
从Windows > Core添加参考Windows
现在你需要添加这段代码:
using Windows.UI.Notifications;
您将能够使用此代码发送通知:
var toast = new ToastNotification(doc);
ToastNotificationManager.CreateToastNotifier().Show(toast);
参考:How to call WinRT APIs in Windows 8 from C# Desktop Applications - WinRT Diagram
【讨论】:
编辑后,我的控制台应用程序没有以引用错误启动:无法加载文件或程序集'System.Runtime,Version=4.0.20.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a'跨度> 它有效,这是 MS 建议的,但这不是最好的方法。这会导致应用程序复制大量 DLL。如果您只是手动添加所需的五个或六个引用,则无需一个额外的 DLL,只需使用系统程序集即可使其工作。【参考方案2】:我在使用 Evaldas B 的代码时遇到了一些问题,我缺少一个字符串。 (这里说需要字符串)
.CreateToastNotifier(<needed a string here>).Show(toast);
警告我是 C# 的新手,所以我的代码可能很糟糕——但它确实有效,而且非常简单,对于我找到的大多数解决方案来说,这比我能说的要多
另外,我在阅读 xml 文档时也遇到了麻烦。我正在与 System.xml(我认为)和 Windows.Data.Dom.Xml(也不完全确定)作斗争。 最后,我决定为我的示例文件制作硬编码字符串,并使用 switch 语句在它们之间切换。 我找到了很多人,在堆栈溢出时寻找我想出的解决方案。似乎将 toast 通知系统与控制台或后台应用程序一起使用会非常有用,并且围绕带有 windows 应用程序的 toast 通知系统的文档都表明它需要与应用程序一起使用。操作中心对于通知与 NotificationTray/NotifyIcon 路由非常有用。我在网络上的其他任何地方都没有找到完整的解决方案。这是示例代码。
/*
At first you need to declare that your program will be using winRT libraries:
1. Right click on your yourProject, select Unload Project
2. Right click on your youProject(unavailable) and click Edit yourProject.csproj
3. Add a new property group:<TargetPlatformVersion>8.0</TargetPlatformVersion>
4. Reload project
5. Add referece Windows from Windows > Core
*/
using System;
using Windows.Data.Xml.Dom;
using Windows.Storage;
using Windows.Storage.Streams;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Notifications;
namespace ConsoleApplication6
public class NewToastNotification
public NewToastNotification(string input, int type)
string NotificationTextThing = input;
string Toast = "";
switch (type)
case 1:
//Basic Toast
Toast = "<toast><visual><binding template=\"ToastImageAndText01\"><text id = \"1\" >";
Toast += NotificationTextThing;
Toast += "</text></binding></visual></toast>";
break;
default:
Toast = "<toast><visual><binding template=\"ToastImageAndText01\"><text id = \"1\" >";
Toast += "Default Text String";
Toast += "</text></binding></visual></toast>";
break;
XmlDocument tileXml = new XmlDocument();
tileXml.LoadXml(Toast);
var toast = new ToastNotification(tileXml);
ToastNotificationManager.CreateToastNotifier("New Toast Thing").Show(toast);
class Program
static void Main(string[] args)
NewToastNotification Window = new NewToastNotification("Yes",1);
【讨论】:
有人对此有答案吗?传递给 CreateToastNotifier 调用的应用程序 ID 应该是什么?如何找到该应用程序ID?我尝试了许多可能的变化来查看通用应用程序清单,但没有一个起作用。显示吐司,好吧,但是当我点击通用应用程序内的按钮时,没有启动。实际上,在我的情况下,通用应用程序是桌面桥通用应用程序,WPF 包装在 UWP 容器中。【参考方案3】:1) 要使用控制台或桌面应用程序显示 Toast 通知,您的应用程序必须在开始菜单上有快捷方式。
2) 要让应用程序在 Windows 的开始菜单中有快捷图标(不是磁贴图标),您的应用程序必须有一个 AppId。 要为您的应用程序创建一个快捷方式,请创建一个名为 ShellHelpers.cs 的新类并将此代码粘贴到其中。
using System;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.WindowsAPICodePack.Shell.PropertySystem;
using MS.WindowsAPICodePack.Internal;
namespace DesktopToastsSample.ShellHelpers
internal enum STGM : long
STGM_READ = 0x00000000L,
STGM_WRITE = 0x00000001L,
STGM_READWRITE = 0x00000002L,
STGM_SHARE_DENY_NONE = 0x00000040L,
STGM_SHARE_DENY_READ = 0x00000030L,
STGM_SHARE_DENY_WRITE = 0x00000020L,
STGM_SHARE_EXCLUSIVE = 0x00000010L,
STGM_PRIORITY = 0x00040000L,
STGM_CREATE = 0x00001000L,
STGM_CONVERT = 0x00020000L,
STGM_FAILIFTHERE = 0x00000000L,
STGM_DIRECT = 0x00000000L,
STGM_TRANSACTED = 0x00010000L,
STGM_NOSCRATCH = 0x00100000L,
STGM_NOSNAPSHOT = 0x00200000L,
STGM_SIMPLE = 0x08000000L,
STGM_DIRECT_SWMR = 0x00400000L,
STGM_DELETEONRELEASE = 0x04000000L,
internal static class ShellIIDGuid
internal const string IShellLinkW = "000214F9-0000-0000-C000-000000000046";
internal const string CShellLink = "00021401-0000-0000-C000-000000000046";
internal const string IPersistFile = "0000010b-0000-0000-C000-000000000046";
internal const string IPropertyStore = "886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99";
[ComImport,
Guid(ShellIIDGuid.IShellLinkW),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IShellLinkW
UInt32 GetPath(
[Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile,
int cchMaxPath,
//ref _WIN32_FIND_DATAW pfd,
IntPtr pfd,
uint fFlags);
UInt32 GetIDList(out IntPtr ppidl);
UInt32 SetIDList(IntPtr pidl);
UInt32 GetDescription(
[Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile,
int cchMaxName);
UInt32 SetDescription(
[MarshalAs(UnmanagedType.LPWStr)] string pszName);
UInt32 GetWorkingDirectory(
[Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir,
int cchMaxPath
);
UInt32 SetWorkingDirectory(
[MarshalAs(UnmanagedType.LPWStr)] string pszDir);
UInt32 GetArguments(
[Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs,
int cchMaxPath);
UInt32 SetArguments(
[MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
UInt32 GetHotKey(out short wHotKey);
UInt32 SetHotKey(short wHotKey);
UInt32 GetShowCmd(out uint iShowCmd);
UInt32 SetShowCmd(uint iShowCmd);
UInt32 GetIconLocation(
[Out(), MarshalAs(UnmanagedType.LPWStr)] out StringBuilder pszIconPath,
int cchIconPath,
out int iIcon);
UInt32 SetIconLocation(
[MarshalAs(UnmanagedType.LPWStr)] string pszIconPath,
int iIcon);
UInt32 SetRelativePath(
[MarshalAs(UnmanagedType.LPWStr)] string pszPathRel,
uint dwReserved);
UInt32 Resolve(IntPtr hwnd, uint fFlags);
UInt32 SetPath(
[MarshalAs(UnmanagedType.LPWStr)] string pszFile);
[ComImport,
Guid(ShellIIDGuid.IPersistFile),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IPersistFile
UInt32 GetCurFile(
[Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile
);
UInt32 IsDirty();
UInt32 Load(
[MarshalAs(UnmanagedType.LPWStr)] string pszFileName,
[MarshalAs(UnmanagedType.U4)] STGM dwMode);
UInt32 Save(
[MarshalAs(UnmanagedType.LPWStr)] string pszFileName,
bool fRemember);
UInt32 SaveCompleted(
[MarshalAs(UnmanagedType.LPWStr)] string pszFileName);
[ComImport]
[Guid(ShellIIDGuid.IPropertyStore)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IPropertyStore
UInt32 GetCount([Out] out uint propertyCount);
UInt32 GetAt([In] uint propertyIndex, out PropertyKey key);
UInt32 GetValue([In] ref PropertyKey key, [Out] PropVariant pv);
UInt32 SetValue([In] ref PropertyKey key, [In] PropVariant pv);
UInt32 Commit();
[ComImport,
Guid(ShellIIDGuid.CShellLink),
ClassInterface(ClassInterfaceType.None)]
internal class CShellLink
public static class ErrorHelper
public static void VerifySucceeded(UInt32 hresult)
if (hresult > 1)
throw new Exception("Failed with HRESULT: " + hresult.ToString("X"));
用于创建快捷方式的代码(此代码可以添加到您将显示 toast 的同一类中)
public bool TryCreateShortcut()
String shortcutPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Microsoft\\Windows\\Start Menu\\Programs\\FixSus Toasts Sample .lnk";
if (!File.Exists(shortcutPath))
InstallShortcut(shortcutPath);
return true;
return false;
private void InstallShortcut(String shortcutPath)
// Find the path to the current executable
String exePath = Process.GetCurrentProcess().MainModule.FileName;
IShellLinkW newShortcut = (IShellLinkW)new CShellLink();
// Create a shortcut to the exe
DesktopToastsSample.ShellHelpers.ErrorHelper.VerifySucceeded(newShortcut.SetPath(exePath));
DesktopToastsSample.ShellHelpers.ErrorHelper.VerifySucceeded(newShortcut.SetArguments(""));
// Open the shortcut property store, set the AppUserModelId property
IPropertyStore newShortcutProperties = (IPropertyStore)newShortcut;
using (PropVariant appId = new PropVariant(APP_ID))
DesktopToastsSample.ShellHelpers.ErrorHelper.VerifySucceeded(newShortcutProperties.SetValue(SystemProperties.System.AppUserModel.ID, appId));
DesktopToastsSample.ShellHelpers.ErrorHelper.VerifySucceeded(newShortcutProperties.Commit());
// Commit the shortcut to disk
IPersistFile newShortcutSave = (IPersistFile)newShortcut;
DesktopToastsSample.ShellHelpers.ErrorHelper.VerifySucceeded(newShortcutSave.Save(shortcutPath, true));
现在您可以创建一个展示祝酒词
// Get a toast XML template
XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastImageAndText04);
// Fill in the text elements
XmlNodeList stringElements = toastXml.GetElementsByTagName("text");
stringElements[1].AppendChild(toastXml.CreateTextNode("Message" + newMessage));
// Specify the absolute path to an image
string codeWebFolderPath = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, @"..\..\"));
String imagePath = "file:///" + Path.GetFullPath(codeWebFolderPath+ "Resources\\FixSus.png");
XmlNodeList imageElements = toastXml.GetElementsByTagName("image");
imageElements[0].Attributes.GetNamedItem("src").NodeValue = imagePath;
// Create the toast and attach event listeners
ToastNotification toast = new ToastNotification(toastXml);
toast.Activated += ToastActivated;
toast.Dismissed += ToastDismissed;
toast.Failed += ToastFailed;
// Show the toast. Be sure to specify the AppUserModelId on your application's shortcut!
ToastNotificationManager.CreateToastNotifier(APP_ID).Show(toast);
APP_ID 可以是任何字符串。就我而言,它是“NotificationTest.KEY” 注意:不要修改 ShellHelper 类。 编辑:首先遵循 Evaldas B 的回答,然后应用此解决方案。
【讨论】:
如何在快捷方式中保存 CLSID?以上是关于是否可以从控制台应用程序发送 Toast 通知?的主要内容,如果未能解决你的问题,请参考以下文章
在 Android 中执行点击操作后,如何从通知中发送 Toast?
Windows Phone 8 中的 Toast 通知在 10 秒后消失
从 Windows 服务发送 toast 通知会引发 HRESULT: 0x80070005 (E_ACCESSDENIED)