af Lars Olsen, Consultant
Toast Notifications: This blogpost will help you to educate your users through Windows Toast messages, but the focus of this blog is to teach users to reboot more often – since that still is the way to install big critical updates in Windows 10.
Challenge
We all know that creeping sensation, when Microsoft releases a new critical patch to Windows, and it requires a reboot to finalize the installation, and the mob of users ignores your repeated politically correct formatted messages on the intranet. As administrators we must admit that what seems logical to computer wizz’ like us, is absolutely irrelevant to the average user, and most users, or opponents, are very average.
Goal
What if you could inform a specific user, that he/she is violating company policy with their ignorant behavior. Wouldn’t it be nice if you could put a sign in the face of the offender, without spamming the intranet with warnings to every user in the company? This is the smart bomb of user education utilizing PowerShell and Windows Toast notifications.
Prerequisites
First of we need to get some prerequisites straight, and there isn’t much to it. The only thing you need is Windows PowerShell ISE. For distribution in your company I recommend the World’s best software deployment tool CapaInstaller from CapaSystems.
Scope
This is only intended for Windows 10 but is also supported on Windows 7 – with the latest service pack. Are you ready? Here we go.
How to
Windows keeps track of how many seconds the current session has been running, it also tracks how many times the system has been booted.
To find out how long the current session has been running, we need to do some PowerShell WMI trickery.
$uptime = [int]((get-date)-[system.management.managementdatetimeconverter]::todatetime((get-wmiobject -class win32_operatingsystem).Lastbootuptime)).TotalSeconds
Now we know how many seconds the current session has been running for, but you would confuse the users if you presented them with this message:
More user-friendly time format
To make the time format more user-friendly, we need to do some low-tech PowerShell wizardry.
$days = New-TimeSpan -Seconds $uptime
$days = [String]$days
$days = $days -replace ‘^(.*?):(.)()’,’$1 hours $2 ‘
$days = $days -replace ‘\.’,’ days ‘
$days = $days -replace ‘\:’,’ minutes ‘
$days = “$days seconds”
We convert seconds to a timespan, afterwards we do some replacing and adds text to make it nice and pretty. If you don’t like the way I’ve done the replacing/addition of text, then I encourage you to explore the many ways you can modify variables with PowerShell.
Modified code – from me to you
And now for the fun part – presenting the information in the toast message. The code below is copied and modified from Microsoft, and a full guide to creating custom toast messages can be found here.
To include the modified time format from the variable $days in the body text, I use the variable below.
$BodyText = ‘<text>Your computer has not been rebootet in ‘+ $days + ‘. Please reboot your computer as soon as possible.</text>’
Modify this line in the script, to change the icon used in the toaster. To modify the text on the button, edit the line below.
This is how the new toast message looks:
You can add a check in the script to avoid warning users that have recently rebooted their computer.
Information: If the threshold for displaying the warning is a week, a week is 604800 seconds long.
Toast notifications can be used for many things, such as warning users about coming updates, missing reboot or too many files located on the desktop.
Have fun educating your users.
Below is the entire script. Remember to put a logo.png file in the “c:temp” folder, or edit the script use another file.
The entire script
$uptime = [int]((get-date)-[system.management.managementdatetimeconverter]::todatetime((get-wmiobject -class win32_operatingsystem).Lastbootuptime)).TotalSeconds
$days = New-TimeSpan -Seconds $uptime
$days = [String]$days
$days = $days -replace ‘^(.*?):(.)()’,’$1 hours $2 ‘
$days = $days -replace ‘\.’,’ days ‘
$days = $days -replace ‘\:’,’ minutes ‘
$days = “$days seconds”
$app = ‘{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}\WindowsPowerShell\v1.0\powershell.exe’
[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime]
$Template = [Windows.UI.Notifications.ToastTemplateType]::ToastImageAndText01
$BodyText = ‘<text>Your computer has not been rebootet in ‘+ $days + ‘. Please reboot your computer as soon as possible.</text>’
#Gets the Template XML so we can manipulate the values
[xml]$ToastTemplate = ([Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent($Template).GetXml())
[xml]$ToastTemplate = @”
<toast scenario=”reminder” launch=”app-defined-string”>
<visual>
<binding template=”ToastGeneric”>
<text>Reboot Reminder</text>
$BodyText
<image placement=”AppLogoOverride” src=”C:\Temp\logo.png” />
</binding>
</visual>
<actions>
<action activationType=”background” content=”Understood – i’ll get it done!” arguments=”later”/> </actions>
</toast>
“@
$ToastXml = New-Object -TypeName Windows.Data.Xml.Dom.XmlDocument
$ToastXml.LoadXml($ToastTemplate.OuterXml)
$notify = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($app)
$notify.Show($ToastXml)