Popping Toast Notifications in PowerShell Core

If you’ve ever popped a toast notification in PowerShell using the Windows Runtime (WinRT), you’ve probably discovered that, whilst it works fine in PowerShell 5, it doesn’t work at all in PowerShell Core (5/6/7+). That’s because the WinRT assemblies are not included in PowerShell Core – WinRT is an exclusively Windows thing and PowerShell Core is intended for cross-platform use.

That being said, you can still pop a toast notification with PS Core using much the same code you use for PowerShell 5 – you just need to reference a couple of dlls from the Windows SDK.

Below is some example code which will pop a simple toast notification in either PS 5 or PS 6+. For PowerShell Core, it will install the Microsoft.Windows.SDK.NET.Ref NuGet package for the current user which contains the required dlls.

If ($PSVersionTable.PSVersion.Major -lt 6)
{
$null = [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime]
$null = [Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime]
}
else
{
# Check for the NuGet package provider and install it if necessary
if ($null -eq (Get-PackageProvider -Name NuGet))
{
try
{
$null = Install-PackageProvider -Name NuGet -Force -Scope CurrentUser -ErrorAction Stop
}
catch
{
throw $_.Exception.Message
}
}
# Check for the Microsoft.Windows.SDK.NET.Ref NuGet package and install it if necessary
If ($null -eq (Get-Package -ProviderName NuGet -Name Microsoft.Windows.SDK.NET.Ref -AllVersions -ErrorAction SilentlyContinue))
{
try
{
$null = Install-Package -Name Microsoft.Windows.SDK.NET.Ref -ProviderName NuGet -Force -Scope CurrentUser -ErrorAction Stop
}
catch
{
throw $_.Exception.Message
}
}
# Get the latest version of the WinRT.Runtime.dll and Microsoft.Windows.SDK.NET.dll files
$WinRTRuntime = Get-ChildItem -Path "$env:LOCALAPPDATA\PackageManagement\NuGet\Packages\Microsoft.Windows.SDK.NET.Ref.*" -Filter "WinRT.Runtime.dll" -Recurse -ErrorAction SilentlyContinue |
Sort-Object -Property VersionInfo.FileVersion -Desc | Select -ExpandProperty FullName | Select -First 1
$WinSDKNet = Get-ChildItem -Path "$env:LOCALAPPDATA\PackageManagement\NuGet\Packages\Microsoft.Windows.SDK.NET.Ref.*" -Filter "Microsoft.Windows.SDK.NET.dll" -Recurse -ErrorAction SilentlyContinue |
Sort-Object -Property VersionInfo.FileVersion -Desc | Select -ExpandProperty FullName | Select -First 1
# Load the WinRT.Runtime.dll and Microsoft.Windows.SDK.NET.dll files
Add-Type -Path $WinRTRuntime -ErrorAction Stop
Add-Type -Path $WinSDKNet -ErrorAction Stop
}
# Notification parameters
$Title = "Hello matey!"
$AudioSource = "ms-winsoundevent:Notification.Default"
$SubtitleText = "I say, ol' chap, it's time for a brew. Polly put the kettle on, and all that. While you prepare a cuppa, we'll install some updates."
# Define the toast notification in XML format
[xml]$ToastTemplate = @"
<toast duration="long">
<visual>
<binding template="ToastGeneric">
<text>Windows Updates – you know you love 'em</text>
<group>
<subgroup>
<text hint-style="title" hint-wrap="true" >$Title</text>
</subgroup>
</group>
<group>
<subgroup>
<text hint-style="subtitle" hint-wrap="true" >$SubtitleText</text>
</subgroup>
</group>
</binding>
</visual>
<audio src="$AudioSource"/>
</toast>
"@
# Load the notification into the required format
$ToastXml = New-Object -TypeName Windows.Data.Xml.Dom.XmlDocument
$ToastXml.LoadXml($ToastTemplate.OuterXml)
# Display
$App = "Windows.SystemToast.WindowsUpdate.MoNotification2"
[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($App).Show($ToastXml)

Alternatively you can use the excellent BurntToast PowerShell module, which works on PS Core and makes use of the Windows Community Toolkit to display toast notifications.