Created
May 29, 2025 18:12
-
-
Save hexagr/adfaf53ede2dd49fb75b376118a7d522 to your computer and use it in GitHub Desktop.
Toast Notifications on Windows 11
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| $ShortcutPath = "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\MyToastApp.lnk" | |
| $TargetPath = "C:\Path\To\YourApp.exe" | |
| $AppUserModelID = "Your.App.ID" | |
| Add-Type -TypeDefinition @" | |
| using System; | |
| using System.Runtime.InteropServices; | |
| using System.Runtime.InteropServices.ComTypes; | |
| [ComImport] | |
| [Guid("00021401-0000-0000-C000-000000000046")] | |
| class ShellLink {} | |
| [ComImport] | |
| [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | |
| [Guid("000214F9-0000-0000-C000-000000000046")] | |
| interface IShellLinkW { | |
| void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] System.Text.StringBuilder pszFile, int cchMaxPath, out IntPtr pfd, int fFlags); | |
| void GetIDList(out IntPtr ppidl); | |
| void SetIDList(IntPtr pidl); | |
| void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] System.Text.StringBuilder pszName, int cchMaxName); | |
| void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); | |
| void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] System.Text.StringBuilder pszDir, int cchMaxPath); | |
| void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); | |
| void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] System.Text.StringBuilder pszArgs, int cchMaxPath); | |
| void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); | |
| void GetHotkey(out short pwHotkey); | |
| void SetHotkey(short wHotkey); | |
| void GetShowCmd(out int piShowCmd); | |
| void SetShowCmd(int iShowCmd); | |
| void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] System.Text.StringBuilder pszIconPath, int cchIconPath, out int piIcon); | |
| void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); | |
| void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved); | |
| void Resolve(IntPtr hwnd, int fFlags); | |
| void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); | |
| } | |
| [ComImport] | |
| [Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")] | |
| [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | |
| interface IPropertyStore { | |
| void GetCount(out uint cProps); | |
| void GetAt(uint iProp, out PROPERTYKEY pkey); | |
| void GetValue(ref PROPERTYKEY key, out PROPVARIANT pv); | |
| void SetValue(ref PROPERTYKEY key, ref PROPVARIANT pv); | |
| void Commit(); | |
| } | |
| [StructLayout(LayoutKind.Sequential, Pack = 4)] | |
| struct PROPERTYKEY { | |
| public Guid fmtid; | |
| public uint pid; | |
| } | |
| [StructLayout(LayoutKind.Explicit)] | |
| struct PROPVARIANT { | |
| [FieldOffset(0)] | |
| public ushort vt; | |
| [FieldOffset(8)] | |
| public IntPtr pszVal; | |
| public static PROPVARIANT FromString(string value) { | |
| var pv = new PROPVARIANT(); | |
| pv.vt = 31; // VT_LPWSTR | |
| pv.pszVal = Marshal.StringToCoTaskMemUni(value); | |
| return pv; | |
| } | |
| } | |
| public static class ShellLinkHelper { | |
| static readonly Guid PKEY_AppUserModel_ID_fmtid = new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"); | |
| const uint PKEY_AppUserModel_ID_pid = 5; | |
| public static void CreateShortcut(string shortcutPath, string exePath, string appId) { | |
| var link = (IShellLinkW)new ShellLink(); | |
| link.SetPath(exePath); | |
| var store = (IPropertyStore)link; | |
| var key = new PROPERTYKEY() { fmtid = PKEY_AppUserModel_ID_fmtid, pid = PKEY_AppUserModel_ID_pid }; | |
| var pv = PROPVARIANT.FromString(appId); | |
| store.SetValue(ref key, ref pv); | |
| store.Commit(); | |
| var file = (IPersistFile)link; | |
| file.Save(shortcutPath, false); | |
| } | |
| } | |
| "@ -Language CSharp | |
| # Call the helper from PowerShell | |
| [ShellLinkHelper]::CreateShortcut($ShortcutPath, $TargetPath, $AppUserModelID) | |
| Write-Host "Shortcut created at $ShortcutPath with AppUserModelID = $AppUserModelID" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <windows.h> | |
| #include <wrl/client.h> | |
| #include <wrl/wrappers/corewrappers.h> | |
| #include <windows.ui.notifications.h> | |
| #include <winrt/base.h> | |
| #include <winrt/Windows.Data.Xml.Dom.h> | |
| #include <winrt/Windows.UI.Notifications.h> | |
| #include <string> | |
| #include <iostream> | |
| #include <shobjidl.h> | |
| #pragma comment(lib, "Shell32.lib") | |
| using namespace Microsoft::WRL; | |
| using namespace Microsoft::WRL::Wrappers; | |
| using namespace winrt; | |
| using namespace winrt::Windows::Data::Xml::Dom; | |
| using namespace winrt::Windows::UI::Notifications; | |
| int main() { | |
| RoInitialize(RO_INIT_SINGLETHREADED); | |
| // Set AppUserModelID | |
| SetCurrentProcessExplicitAppUserModelID(L"Your.App.ID"); | |
| // Create Toast Notifier | |
| auto toastNotifier = ToastNotificationManager::CreateToastNotifier(L"Your.App.ID"); | |
| // Create XML content | |
| XmlDocument toastXml; | |
| try { | |
| std::wstring xmlString = L"<toast><visual><binding template='ToastGeneric'><text>Hello from C++!</text></binding></visual></toast>"; | |
| toastXml.LoadXml(xmlString); | |
| } | |
| catch (const hresult_error& ex) { | |
| std::wcerr << L"Failed to load XML: " << ex.message().c_str() << std::endl; | |
| RoUninitialize(); | |
| return 1; | |
| } | |
| // Create Toast Notification | |
| auto toast = ToastNotification(toastXml); | |
| // Show Toast | |
| toastNotifier.Show(toast); | |
| RoUninitialize(); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment