Search code examples
powershelltoast

Powershell toast questions


I am trying to send a toast notification via Powershell, and running on my localhost it works great. I have 2 methods to generate a toast: one is using the BurntToast module, and another is using XML and UI.Notifications. I am impartial to either method, and both are mostly working, but both are also giving me issues. The end goal is to have the script run on a different server using PowerShell Universal which will then remote into the device and generate the toast.

Method 1: BurntToast

First, here is the code for BurntToast:

[string]$Header = 'Read this toast'
[string]$Body = 'Click the button below to view more information'
[string]$RedirectURL = 'https://www.youtube.com/watch?v=8ybW48rKBME&t'
[string]$HeroImage = 'https://files.worldwildlife.org/wwfcmsprod/images/Sea_Turtle_Hol_Chan_Marine_Reserve_WW1105958/hero_small/5fv88fm3v6_Sea_Turtle_Hol_Chan_Marine_Reserve_WW1105958.jpg'
[string]$AppLogo = 'https://images.fineartamerica.com/images/artworkimages/mediumlarge/3/small-sea-turtle-chelonioidea-swimming-inside-a-shallow-sea-joaquin-corbalan.jpg'
$Button = New-BTButton -Content 'Click here to view' -Arguments $RedirectURL
New-BurntToastNotification -Text $Header, $Body -Button $Button -AppLogo $AppLogo -HeroImage $HeroImage

When running from my localhost it runs perfectly, even when I encompass everything in an Invoke-Command. BurntToast successful

However, when I run it from PowerShell Universal none of the images carry over. I am using Invoke-Command on my machine name. The toast gets sent, and the button shows the correct link, but the toast shows no images.

BurntToast no images

Method 2: XML and UI.Notifications

Here is the code for UI.Notifications. I have it wrapped in an Invoke-Command because it does not appear to work well with Powershell 7. Copying/pasting everything inside the brackets to PS 5 terminal works great.

Invoke-Command -ComputerName localhost -ScriptBlock {
[string]$Header = 'New Toast'
[string]$Body = 'Please click the button to view more information'
[string]$RedirectURL = 'https://www.youtube.com/watch?v=8ybW48rKBME&t'
[string]$HeroImage = 'https://files.worldwildlife.org/wwfcmsprod/images/Sea_Turtle_Hol_Chan_Marine_Reserve_WW1105958/hero_small/5fv88fm3v6_Sea_Turtle_Hol_Chan_Marine_Reserve_WW1105958.jpg'
[string]$AppLogo = 'https://images.fineartamerica.com/images/artworkimages/mediumlarge/3/small-sea-turtle-chelonioidea-swimming-inside-a-shallow-sea-joaquin-corbalan.jpg'
$xml = @"
<toast>

<visual>
    <binding template="ToastGeneric">
    <image placement="appLogoOverride" hint-crop="circle" src="$AppLogo"/>
    <text>$Header</text>
    <text>$Body</text>
    <image src="$HeroImage"/>
    </binding>
</visual>

<actions>
    <action content="View Page" activationType="protocol" arguments="$RedirectURL" />
</actions>

</toast>
"@
$xml = $xml.Replace('&','&amp;')
$XmlDocument = [Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime]::New()
$XmlDocument.loadXml($xml)
$AppId = 'Microsoft.WindowsTerminal_8wekyb3d8bbwe!App'
[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime]::CreateToastNotifier($AppId).Show($XmlDocument)
}

XML example

This also works successfully, from both localhost and PSU. The button works fine, as doess the X to close it, but I noticed that when I click anything else like the image or text it prompts a Windows popup asking if Terminal can make changes to your device, requiring admin consent. This happens when I run it locally, and from PSU.

In short, I am looking for a solution to either method, with either one of these issues:

  • BurntToast not displaying images when running from a third-party application
  • UI.Notifications prompting an admin consent popup

Has anybody else had success with either of these in the past?


Solution

  • First - Oof. I've been rickrolled. :P

    Ok - I've tried replicating this in my environment (W10 22H2 / PowerShell 5.1) and have had some progress & mixed results.

    Here's what I've got based on your code:

    [string]$Header = 'New Toast'
    [string]$Body = 'Please click the button to view more information'
    [string]$RedirectURL = [System.Security.SecurityElement]::Escape('https://www.youtube.com/watch?v=8ybW48rKBME&t')
    [string]$HeroImage = [System.Security.SecurityElement]::Escape('https://files.worldwildlife.org/wwfcmsprod/images/Sea_Turtle_Hol_Chan_Marine_Reserve_WW1105958/hero_small/5fv88fm3v6_Sea_Turtle_Hol_Chan_Marine_Reserve_WW1105958.jpg')
    [string]$AppLogo = [System.Security.SecurityElement]::Escape('https://images.fineartamerica.com/images/artworkimages/mediumlarge/3/small-sea-turtle-chelonioidea-swimming-inside-a-shallow-sea-joaquin-corbalan.jpg')
    
    $appId = '{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}\WindowsPowerShell\v1.0\powershell.exe'
    $null = [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime]
    $null = [Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime]
    
    $xml = @"
    <toast>
      <visual>
        <binding template="ToastGeneric">
            <image placement="appLogoOverride" hint-crop="circle" src="$AppLogo"/>
            <text>$Header</text>
            <text>$Body</text>
            <image src="$HeroImage"/>
        </binding>
      </visual>
      <actions>
        <action content="View Page" activationType="protocol" arguments="$RedirectURL" />
      </actions>
    </toast>
    "@
    
    $toastXml = [Windows.Data.Xml.Dom.XmlDocument]::new()
    $toastXml.LoadXml($xml)
    $toast = [Windows.UI.Notifications.ToastNotification]::new($toastXml)
    [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($appId).Show($toast)
    

    Please draw your attention to the "[System.Security.SecurityElement]::Escape()" portions for the redirect url etc. This bypasses the XML parser for those entities.

    Also, please note that the app I'm calling is different than yours. I'm calling powershell rather than terminal.

    Additionally, I've been unsuccessful with getting the images to pull down remotely/live. I think it's a limitation of 5.1/powershell versus your method of utilizing 7/terminal, your results may vary. I would suggest considering having either the images be located with the script, or dynamically downloaded to a place the script can find & called locally.

    Lastly, BurntToast - I'm left with the feeling that it's functionally abandoned and hasn't really been updated in github in 2 years as of this point. They've done 1-2 prereleases over the past year but nothing official as far as I could see. It might be a little risky using such a module in a prod environment.

    Anyway - I hope this is of some value :)

    PS / Edit - you might want to check out this repo as well (it's a bit older too, but may be some inspiration): https://github.com/imabdk/Toast-Notification-Script