Public/Invoke-ECKRebootToastNotification.ps1

Function Invoke-ECKRebootToastNotification
    {
        Param
            (
                [Parameter(Mandatory = $true, Position=0)]
                [String]$HostScriptPath,
                [Parameter(Mandatory = $false)]
                [String]$SmallLogo, #Image Logo must be PNG and can be submitted as path or Base64
                [Parameter(Mandatory = $false)]
                [String]$Image, #Image Logo must be JPG and can be submitted as path or Base64
                [Parameter(Mandatory = $false)]
                [ValidateSet("top","TOP","Top","bottom","BOTTOM","Bottom")]
                [String]$ImagePosition = "top",
                [Parameter(Mandatory = $false)]
                [ValidateSet("Default","DEFAULT","Default","reminder","REMINDER","Reminder")]
                [String]$ToastScenario = "reminder",
                [Parameter(Mandatory = $false)]
                [String]$ToastTitle = "Reboot requiered",
                [Parameter(Mandatory = $false)]
                [String]$ToastSubTitle,
                [Parameter(Mandatory = $false)]
                [String]$ToastMessage = "Important security updates will be installed after your device restart.`r`n`r`nPlease, reboot to complete the installation !",
                [Parameter(Mandatory = $false)]
                [String]$ToastMessage2 = "",
                [Parameter(Mandatory = $false)]
                [HashTable]$Buttons
            )
        # Set Task names
        $OldTaskName = [char]34 + "*_RebootToast" + $(split-path $HostScriptPath -Leaf).Replace("-","").replace(".ps1","").replace(" ","") +"_*-*-*-*-*" + [char]34
        $TaskName = "RebootToast" + $(split-path $HostScriptPath -Leaf).Replace("-","").replace(".ps1","").replace(" ","")

        # Set Action Folder
        $ActionFld = "C:\ProgramData\RebootToastUI"
        If (-not (test-path $ActionFld)){new-item -Path $ActionFld -ItemType Directory -Force|Out-Null}

        # Set Buttons
        If (-not $Buttons)
            {
                [HashTable]$Buttons = @{'Reboot Now' = @('rebootnow','protocol',"$ActionFld\Button1.ps1") ; 'Snooze (30 Mins)' = @('dismiss','system','') ; 'Button3' = @('','','')}
                $script_Button1 = @"
                    Get-ScheduledTask -TaskName $OldTaskName -ErrorAction SilentlyContinue|Unregister-ScheduledTask -Confirm:`$false -ErrorAction SilentlyContinue
                    Restart-Computer -Confirm:`$false -Force
"@

                $script_Button1|Out-File -FilePath "$ActionFld\Button1.ps1" -Encoding default
            }


        # Register actions
        Foreach ($item in $Buttons.GetEnumerator()){If (($item.Value[0] -ne '') -and (($item.Value[0]).ToUpper() -ne 'DISMISS')){Set-ECKToasTActionProtocol -Action $item.Value[0] -PsFilePath $item.Value[2] }}

        # Convert Logo and Image
        If (-not ([string]::IsNullOrWhiteSpace($Image)))
            {
                $ImagePath = "$ActionFld\hero.jpg"
                If (([System.IO.Path]::GetExtension($Image)).toUpper() -eq ".JPG" -and (Test-path $Image))
                    {
                        Try{Copy-Item -Path $image -Destination $ImagePath -Force -Confirm:$false -ErrorAction SilentlyContinue}
                        Catch{$ImagePath = ""}
                    }
                Else
                    {
                        Try
                            {
                                $Content = [System.Convert]::FromBase64String($Image)
                                Set-Content -Path $ImagePath -Value $Content -Encoding Byte -Force -Confirm:$false
                            }
                        Catch
                            {$ImagePath = ""}
                    }
            }

        If (-not ([string]::IsNullOrWhiteSpace($SmallLogo)))
            {
                $LogoImagePath = "$ActionFld\logo.png"
                If (([System.IO.Path]::GetExtension($SmallLogo)).toUpper() -eq ".PNG" -and (Test-path $SmallLogo))
                    {
                        Try{Copy-Item -Path $SmallLogo -Destination $LogoImagePath -Force -Confirm:$false -ErrorAction SilentlyContinue}
                        Catch{$LogoImagePath = ""}
                    }
                Else
                    {
                        Try
                            {
                                $Content = [System.Convert]::FromBase64String($SmallLogo)
                                Set-Content -Path $LogoImagePath -Value $Content -Encoding Byte -Force -Confirm:$false
                            }
                        Catch
                            {$LogoImagePath = ""}
                    }
            }

        If($ImagePosition.ToUpper() -eq "TOP"){$ImagePos = "hero"} else {$ImagePos = "inline"}

        $Script_Variables = @"
        `$ToastTitle = "$ToastTitle"
        `$ToastSubTitle = "$ToastSubTitle"
        `$ToastMessage = "$ToastMessage"
        `$ToastMessage2 = "$ToastMessage2"
        `$ActionFld = "$ActionFld"
        `$LogoImagePath = "$LogoImagePath"
        `$ImagePath = "$ImagePath"
        `$ToastScenario = "$ToastScenario"
        `$Button3 = @('$($Buttons.GetEnumerator().Name[0])','$($Buttons[$Buttons.GetEnumerator().name[0]][0])','$($Buttons[$Buttons.GetEnumerator().name[0]][1])')
        `$Button2 = @('$($Buttons.GetEnumerator().Name[1])','$($Buttons[$Buttons.GetEnumerator().name[1]][0])','$($Buttons[$Buttons.GetEnumerator().name[1]][1])')
        `$Button1 = @('$($Buttons.GetEnumerator().Name[2])','$($Buttons[$Buttons.GetEnumerator().name[2]][0])','$($Buttons[$Buttons.GetEnumerator().name[2]][1])')
"@


        $script_Notif = {

                # Check for required entries in registry for when using Powershell as application for the toast
                $App = '{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}\WindowsPowerShell\v1.0\powershell.exe'
                $RegPath = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Notifications\Settings"
                if (-NOT(Test-Path -Path "$RegPath\$App")) {New-Item -Path "$RegPath\$App" -Force|Out-Null}
                New-ItemProperty -Path "$RegPath\$App" -Name "ShowInActionCenter" -Value 1 -PropertyType "DWORD" -Force|Out-Null

                #Rebuild Buttons
                $SetButtons = $False
                $Buttons = "<actions>`r`n"
                If ($Button1[1] -ne ''){$Buttons = $Buttons + " <action arguments = '$($Button1[1]):' content = '$($Button1[0])' activationType='$($Button1[2])' />`r`n";$SetButtons = $True}
                If ($Button2[1] -ne ''){$Buttons = $Buttons + " <action arguments = '$($Button2[1]):' content = '$($Button2[0])' activationType='$($Button2[2])' />`r`n";$SetButtons = $True}
                If ($Button3[1] -ne ''){$Buttons = $Buttons + " <action arguments = '$($Button3[1]):' content = '$($Button3[0])' activationType='$($Button3[2])' />`r`n";$SetButtons = $True}
                If ($SetButtons -eq $True){$Buttons = $Buttons + " </actions>"}Else{$Buttons = ''}
                $Buttons = $Buttons.replace('dismiss:','dismiss')

                #Rebuild Images
                If (-not ([string]::IsNullOrWhiteSpace($ImagePath))){$Image = "<image placement='$ImagePos' src='$ImagePath'/>"} Else {$Image = ''}
                If (-not ([string]::IsNullOrWhiteSpace($LogoImagePath))){$LogoImage = "<image placement='appLogoOverride' hint-crop='circle' src='$LogoImagePath'/>"} Else {$LogoImage = ''}

                # Toast Notification (Visual)
                [String]$Toast = @"
                <toast scenario="$ToastScenario">
                    <visual>
                        <binding template="ToastGeneric">
                            <text>$ToastTitle</text>
                            <text>$ToastSubTitle</text>
                            $LogoImage
                            $Image
                            <group>
                                <subgroup>
                                    <text hint-style="body" hint-wrap="true" >$ToastMessage</text>
                                    <text hint-style="body" hint-wrap="true" >$ToastMessage2</text>
                                </subgroup>
                            </group>
                        </binding>
                    </visual>
                    $Buttons
                </toast>
"@


                [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime]|Out-Null
                [Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime]|Out-Null

                # Display Notificaton
                [XML]$Toast = $Toast
                $ToastXml = New-Object -TypeName Windows.Data.Xml.Dom.XmlDocument
                $ToastXml.LoadXml($Toast.OuterXml)
                [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($App).Show($ToastXml)
            }

        $script_Notif = [ScriptBlock]::Create($Script_Variables.ToString() + $script_Notif.ToString())

        # Schedule Task
        Get-ScheduledTask -TaskName $OldTaskName -ErrorAction SilentlyContinue|Unregister-ScheduledTask -Confirm:$false -ErrorAction SilentlyContinue
        $trigger = New-ScheduledTaskTrigger -RepetitionInterval $(New-TimeSpan -Minutes 30) -At $((Get-Date).AddSeconds(5).ToString('s')) -Once
        Invoke-ECKScheduledTask -TaskName $TaskName -ScriptBlock $script_Notif -Context user -triggerObject $Trigger -DontAutokilltask -AllowUsersFullControl -HostScriptPath $HostScriptPath
    }