Skip to content

Added possibility to run any PowerShell code (encoded as base64) using new protocol ToastRunPSBase64 #20

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 87 additions & 30 deletions New-ToastNotification.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -82,18 +82,18 @@
** As well as added support for dynamic deadline retrieval for software updates **
** Stuff has been rewritten to suit my understanding and thoughts of the script **

2.0.0 - Huge changes to how this script handles custom protocols
Added Support for Custom Actions/Protocols within the script under user context removing the need for that to be run under SYSTEM/ADMIN
- <Option Name="Action" Value="ToastRunUpdateID:" />
- <Option Name="Action" Value="ToastRunPackageID:" />
- <Option Name="Action" Value="ToastRunApplicationID:" />
- <Option Name="Action" Value="ToastReboot:" />
Added Support to dynamically create Custom Action Scripts to support Custom Protocols
Added Support for Software (Feature) Updates : Searches for an update and will store in variable
Added new XML Types for Software Updates:
- <Option Name="RunUpdateID" Enabled="True" Value="3012973" />
- <Option Name="RunUpdateTitle" Enabled="True" Value="Version 1909" />
Added support for getting deadline date/time dynamically for software updates
2.0.0 - Huge changes to how this script handles custom protocols
Added Support for Custom Actions/Protocols within the script under user context removing the need for that to be run under SYSTEM/ADMIN
- <Option Name="Action" Value="ToastRunUpdateID:" />
- <Option Name="Action" Value="ToastRunPackageID:" />
- <Option Name="Action" Value="ToastRunApplicationID:" />
- <Option Name="Action" Value="ToastReboot:" />
Added Support to dynamically create Custom Action Scripts to support Custom Protocols
Added Support for Software (Feature) Updates : Searches for an update and will store in variable
Added new XML Types for Software Updates:
- <Option Name="RunUpdateID" Enabled="True" Value="3012973" />
- <Option Name="RunUpdateTitle" Enabled="True" Value="Version 1909" />
Added support for getting deadline date/time dynamically for software updates
- Configure DynamicDeadline with the UpdateID

2.0.1 - Updated custom action scripts!
Expand All @@ -106,7 +106,7 @@
- If newer version is available from the script, new custom action scripts will be created
- This allows me to make sure the relevant scripts are in place in case I change something along the way
- Modified script output of custom script for RunPackageID to pick up Program ID dynamically
Added support for getting deadline date/time dynamically for applications
Added support for getting deadline date/time dynamically for applications
- Configure DynamicDeadline with the Application ID

2.0.2 - Fixed an error in the custom protocols
Expand Down Expand Up @@ -267,21 +267,21 @@ function Get-GivenName() {
if (Get-Service -Name ccmexec -ErrorAction SilentlyContinue) {
Write-Log -Message "Looking for logged on user's SID in WMI with CCM client"
$LoggedOnSID = Get-CimInstance -Namespace ROOT\CCM -Class CCM_UserLogonEvents -Filter "LogoffTime=null" | Select -ExpandProperty UserSID
if ($LoggedOnSID.GetType().IsArray) {
Write-Log -Message "Multiple SID's found logged on. Skipping"
$GivenName = $null
if ($LoggedOnSID.GetType().IsArray) {
Write-Log -Message "Multiple SID's found logged on. Skipping"
$GivenName = $null
}
else {
$RegKey = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\SessionData"
$DisplayName = (Get-ChildItem -Path $RegKey | Where-Object {$_.GetValue("LoggedOnUserSID") -eq $LoggedOnSID} | Select-Object -First 1).GetValue("LoggedOnDisplayName")
if ($DisplayName) {
$GivenName = $DisplayName.Split()[0].Trim()
Write-Log -Message "Given name found matching logged on user SID: $GivenName"
$GivenName
}
else {
$GivenName = $null
}
else {
$RegKey = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\SessionData"
$DisplayName = (Get-ChildItem -Path $RegKey | Where-Object {$_.GetValue("LoggedOnUserSID") -eq $LoggedOnSID} | Select-Object -First 1).GetValue("LoggedOnDisplayName")
if ($DisplayName) {
$GivenName = $DisplayName.Split()[0].Trim()
Write-Log -Message "Given name found matching logged on user SID: $GivenName"
$GivenName
}
else {
$GivenName = $null
}
}
}
}
Expand Down Expand Up @@ -773,7 +773,7 @@ function Write-CustomActionRegistry() {
[CmdletBinding()]
param (
[Parameter(Position="0")]
[ValidateSet("ToastRunApplicationID","ToastRunPackageID","ToastRunUpdateID","ToastReboot")]
[ValidateSet("ToastRunApplicationID", "ToastRunPackageID", "ToastRunUpdateID", "ToastReboot", "ToastRunPSBase64")]
[string]
$ActionType,
[Parameter(Position="1")]
Expand Down Expand Up @@ -842,6 +842,20 @@ function Write-CustomActionRegistry() {
Write-Log -Level Error -Message "Error message: $ErrorMessage"
}
}
ToastRunPSBase64 {
# Build out registry for custom action for running PowerShell command encoded as Base64 via the action button
try {
New-Item "HKCU:\Software\Classes\$($ActionType)\shell\open\command" -Force -ErrorAction SilentlyContinue | Out-Null
New-ItemProperty -LiteralPath "HKCU:\Software\Classes\$($ActionType)" -Name 'URL Protocol' -Value '' -PropertyType String -Force -ErrorAction SilentlyContinue | Out-Null
New-ItemProperty -LiteralPath "HKCU:\Software\Classes\$($ActionType)" -Name '(default)' -Value "URL:$($ActionType) Protocol" -PropertyType String -Force -ErrorAction SilentlyContinue | Out-Null
$RegCommandValue = $RegCommandPath + '\' + "$($ActionType).cmd `"%1`""
New-ItemProperty -LiteralPath "HKCU:\Software\Classes\$($ActionType)\shell\open\command" -Name '(default)' -Value $RegCommandValue -PropertyType String -Force -ErrorAction SilentlyContinue | Out-Null
} catch {
Write-Log -Level Error "Failed to create the $ActionType custom protocol in HKCU\Software\Classes. Action button might not work"
$ErrorMessage = $_.Exception.Message
Write-Log -Level Error -Message "Error message: $ErrorMessage"
}
}
}
}

Expand All @@ -853,7 +867,7 @@ function Write-CustomActionScript() {
[CmdletBinding()]
param (
[Parameter(Position="0")]
[ValidateSet("ToastRunApplicationID","ToastRunPackageID","ToastRunUpdateID","ToastReboot")]
[ValidateSet("ToastRunApplicationID", "ToastRunPackageID", "ToastRunUpdateID", "ToastReboot", "ToastRunPSBase64")]
[string] $Type,
[Parameter(Position="1")]
[String] $Path = $global:CustomScriptsPath
Expand Down Expand Up @@ -1113,13 +1127,48 @@ exit 0
# Do not run another type; break
Break
}
# Create custom scripts to run PowerShell command encoded as Base64 directly from the action button
ToastRunPSBase64 {
try {
$CMDFileName = $Type + '.cmd'
$CMDFilePath = $Path + '\' + $CMDFileName
try {
New-Item -Path $Path -Name $CMDFileName -Force -OutVariable PathInfo | Out-Null
} catch {
$ErrorMessage = $_.Exception.Message
Write-Log -Level Error -Message "Error message: $ErrorMessage"
}
try {
$GetCustomScriptPath = $PathInfo.FullName
[String]$Script = "
set passedArg=%1
:: remove part before : from passed string
set base64=%passedArg:*:=%
powershell.exe -ExecutionPolicy Bypass -NoLogo -NonInteractive -NoProfile -WindowStyle Hidden -EncodedCommand %base64%"
if (-NOT[string]::IsNullOrEmpty($Script)) {
Out-File -FilePath $GetCustomScriptPath -InputObject $Script -Encoding ASCII -Force
}
} catch {
Write-Log -Level Error "Failed to create the custom .cmd script for $Type. Action button might not work"
$ErrorMessage = $_.Exception.Message
Write-Log -Level Error -Message "Error message: $ErrorMessage"
}

} catch {
Write-Log -Level Error "Failed to create the custom .cmd script for $Type. Action button might not work"
$ErrorMessage = $_.Exception.Message
Write-Log -Level Error -Message "Error message: $ErrorMessage"
}
# Do not run another type; break
Break
}
}
}

######### GENERAL VARIABLES #########
# Global variables
# Setting global script version
$global:ScriptVersion = "2.1.0"
$global:ScriptVersion = "2.1.1"
# Setting executing directory
$global:ScriptPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
# Setting global custom action script location
Expand Down Expand Up @@ -1359,6 +1408,12 @@ if(-NOT[string]::IsNullOrEmpty($Xml)) {
}
}

if ($ActionButton1Content -match "^ToastRunPSBase64:\s*$") {
Write-Log -Level Error -Message "Error. Incomplete Value in the $Config file Action1 tag"
Write-Log -Level Error -Message "Error. You have to specify also the base64 encoded PowerShell command: like ToastRunPSBase64:bQBrAGQAaQByACAAQwA6AFwAdABlAG0AcABcAGIAYQBzAGUANgA0AA=="
Exit 1
}

# Check if toast is enabled in config.xml
if ($ToastEnabled -ne "True") {
Write-Log -Message "Toast notification is not enabled. Please check $Config file"
Expand Down Expand Up @@ -1625,10 +1680,12 @@ if ($CreateScriptsProtocolsEnabled -eq "True") {
Write-CustomActionRegistry -ActionType ToastRunApplicationID
Write-CustomActionRegistry -ActionType ToastRunPackageID
Write-CustomActionRegistry -ActionType ToastRunUpdateID
Write-CustomActionRegistry -ActionType ToastRunPSBase64
Write-CustomActionScript -Type ToastReboot
Write-CustomActionScript -Type ToastRunApplicationID
Write-CustomActionScript -Type ToastRunPackageID
Write-CustomActionScript -Type ToastRunUpdateID
Write-CustomActionScript -Type ToastRunPSBase64
New-ItemProperty -Path $global:RegistryPath -Name $RegistryName -Value $global:ScriptVersion -PropertyType "String" -Force | Out-Null
}
catch {
Expand Down
98 changes: 98 additions & 0 deletions config-toast-base64.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<Configuration>
<Feature Name="Toast" Enabled="True" />
<!-- Enables or disables the entire toast notification -->
<Option Name="CreateScriptsAndProtocols" Enabled="True" />
<!-- Automatically create the needed custom scripts and protocols. This removes the need to do scripts and protocols outside of the script -->
<Option Name="UseSoftwareCenterApp" Enabled="True" />
<!-- The app in Windows doing the actual notification - can't be both SoftwareCenter and Powershell -->
<Option Name="LogoImageName" Value="ToastLogoImageWindows.jpg" />
<!-- File name of the image shown as logo in the toast notoification -->
<Option Name="HeroImageName" Value="ToastHeroImageSecurity.jpg" />
<!-- File name of the image shown in the top of the toast notification -->
<Option Name="ActionButton1" Enabled="True" />
<!-- Enables or disables the action button. -->
<Option Name="DismissButton" Enabled="True" />
<!-- Enables or disables the dismiss button. -->
<Option Name="SnoozeButton" Enabled="True" />
<!-- Enabling this option will always enable action button and dismiss button -->
<Option Name="Scenario" Type="reminder" />
<!-- Possible values are: reminder | short | long -->
<Option Name="Action1" Value="ToastRunPSBase64:bQBrAGQAaQByACAAQwA6AFwAdABlAG0AcABcAGIAYQBzAGUANgA0AA==" />
<!-- Action taken when using the Action button. Can be any protocol in Windows -->
<Text Option="GreetGivenName" Enabled="True" />
<!-- Displays the toast with a personal greeting using the users given name retrieved from AD. Will try retrieval from WMI of no local AD -->
<Text Option="MultiLanguageSupport" Enabled="False" />
<!-- Enable support for multiple languages. If set to True, the toast notification will look for the users language culture within the config file -->
<en-US> <!-- Default fallback language. This language will be used if MultiLanguageSupport is set to False or if no matching language is found -->
<Text Name="ActionButton1">Run base64</Text> <!-- Text on the ActionButton if enabled -->
<Text Name="ActionButton2">Learn More</Text> <!-- Text on the ActionButton if enabled -->
<Text Name="DismissButton">Dismiss</Text> <!-- Text on the DismissButton if enabled -->
<Text Name="SnoozeButton">Snooze</Text> <!-- Text on the SnoozeButton if enabled -->
<Text Name="AttributionText">IT Team</Text>
<Text Name="HeaderText">Helpdesk kindly reminds you...</Text>
<Text Name="TitleText">Nejaky nadpis</Text>
<Text Name="BodyText1">kecyyy ;-)</Text>
<Text Name="BodyText2">dojde k vytvoreni adresare C:\temp\base64</Text>
<Text Name="SnoozeText">Click snooze to be reminded again in:</Text>
<Text Name="DeadlineText">Your deadline is:</Text>
<Text Name="GreetMorningText">Good morning</Text>
<Text Name="GreetAfternoonText">Good afternoon</Text>
<Text Name="GreetEveningText">Good evening</Text>
<Text Name="MinutesText">Minutes</Text>
<Text Name="HourText">Hour</Text>
<Text Name="HoursText">Hours</Text>
<Text Name="ComputerUptimeText">Computer uptime:</Text>
<Text Name="ComputerUptimeDaysText">days</Text>
</en-US>
<da-DK>
<Text Name="PendingRebootUptimeText">Din computer er påkrævet at genstarte, da den har overskredet den maksimale oppetid.</Text> <!-- Text used if the PendingRebootUptimeText Option is enabled -->
<Text Name="PendingRebootCheckText">Årsag: Udestående genstart fundet i registry eller WMI.</Text> <!-- Text used if the PendingRebootUptimeText Option is enabled -->
<Text Name="ADPasswordExpirationText">Dit password vil udløbe: </Text> <!-- Text used if the ADPasswordExpirationText Option is enabled -->
<Text Name="CustomAudioTextToSpeech">Hej dig - vågn op. Din computer skal genstarte. Gør det nu.</Text> <!-- Text to speech used if the CustomAudioTextToSpeech Option is enabled -->
<Text Name="ActionButton1">Genstart nu</Text> <!-- Text on the ActionButton if enabled -->
<Text Name="ActionButton2">Mere Info</Text> <!-- Text on the ActionButton if enabled -->
<Text Name="DismissButton">Afvis</Text> <!-- Text on the DismissButton if enabled -->
<Text Name="SnoozeButton">Udskyd</Text> <!-- Text on the SnoozeButton if enabled -->
<Text Name="AttributionText">www.imab.dk</Text>
<Text Name="HeaderText">En venlig påmindelse fra Helpdesk</Text>
<Text Name="TitleText">Din computer skal genstarte!</Text>
<Text Name="BodyText1">Af hensyn til din computers sikkerhed og stabilitet, beder vi dig genstarte din computer snarest muligt.</Text>
<Text Name="BodyText2">At genstarte sin computer regelmæssigt, er med til at sikre et sikkert og stabilt Windows. På forhånd tak.</Text>
<Text Name="SnoozeText">Klik udskyd for at blive påmindet igen om:</Text>
<Text Name="DeadlineText">Din tidsfrist er:</Text>
<Text Name="GreetMorningText">Godmorgen</Text>
<Text Name="GreetAfternoonText">God eftermiddag</Text>
<Text Name="GreetEveningText">Godaften</Text>
<Text Name="MinutesText">Minutter</Text>
<Text Name="HourText">Time</Text>
<Text Name="HoursText">Timer</Text>
<Text Name="ComputerUptimeText">Computer oppetid:</Text>
<Text Name="ComputerUptimeDaysText">dage</Text>
</da-DK>
<sv-SE>
<Text Name="PendingRebootUptimeText">Din dator behöver startas om då den överskridit den maximala tillåtna upptiden.</Text> <!-- Text used if the PendingRebootUptimeText Option is enabled -->
<Text Name="PendingRebootCheckText">Orsak: Väntande omstart hittades i registret eller WMI.</Text> <!-- Text used if the PendingRebootUptimeText Option is enabled -->
<Text Name="ADPasswordExpirationText">Ditt lösenord går ut: </Text> <!-- Text used if the ADPasswordExpirationText Option is enabled -->
<Text Name="CustomAudioTextToSpeech">Hej du - vakna upp. Datorn måste starta om. Gör det nu.</Text> <!-- Text to speech used if the CustomAudioTextToSpeech Option is enabled -->
<Text Name="ActionButton1">Starta Om</Text> <!-- Text on the ActionButton if enabled -->
<Text Name="ActionButton2">Starta Om</Text> <!-- Text on the ActionButton if enabled -->
<Text Name="DismissButton">Stäng</Text> <!-- Text on the DismissButton if enabled -->
<Text Name="SnoozeButton">Påminn</Text> <!-- Text on the SnoozeButton if enabled -->
<Text Name="AttributionText">www.imab.dk</Text>
<Text Name="HeaderText">En vänlig påminnelse från IT...</Text>
<Text Name="TitleText">Din dator behövs starta om</Text>
<Text Name="BodyText1">För att kunna garantera datorns säkerhet och stabilitet ber vi dig att starta om datorn så snart som möjligt.</Text>
<Text Name="BodyText2">Att starta om sin dator regelbundet bidrar till en stabilare och säkrare It-miljö. Tack på förhand!</Text>
<Text Name="SnoozeText">Klicka på Påminn för att bli påmind igen:</Text>
<Text Name="DeadlineText">Slutdatum är:</Text>
<Text Name="GreetMorningText">God morgon</Text>
<Text Name="GreetAfternoonText">God eftermiddag</Text>
<Text Name="GreetEveningText">God kväll</Text>
<Text Name="MinutesText">Minuter</Text>
<Text Name="HourText">Timma</Text>
<Text Name="HoursText">Timmar</Text>
<Text Name="ComputerUptimeText">Datorns upptid:</Text>
<Text Name="ComputerUptimeDaysText">dagar</Text>
</sv-SE>
</Configuration>
Loading