From e5a7f10adec38c08397c7d95529c84822f79b441 Mon Sep 17 00:00:00 2001 From: GraceSolutions Date: Thu, 10 Apr 2025 21:12:20 -0400 Subject: [PATCH] Update PowerShell module to use Write-Output instead of Write-Host and load assembly through PSD1 --- PowerShell/README.md | 205 ++++---------- PowerShell/WindowsNotifications.psd1 | 131 +++------ PowerShell/WindowsNotifications.psm1 | 402 +++++++-------------------- 3 files changed, 195 insertions(+), 543 deletions(-) diff --git a/PowerShell/README.md b/PowerShell/README.md index 6fa1667..5709cf3 100644 --- a/PowerShell/README.md +++ b/PowerShell/README.md @@ -1,6 +1,6 @@ -# WindowsNotifications PowerShell Module +# Windows Notifications PowerShell Module -This PowerShell module provides a convenient way to use the Windows Notifications library from PowerShell scripts. +This PowerShell module provides a simple interface to the Windows Notifications library, allowing you to display notifications in user context from SYSTEM. ## Installation @@ -17,22 +17,17 @@ This PowerShell module provides a convenient way to use the Windows Notification ## Usage -### Initialize the Module - -Before using the module, you need to initialize it: +### Initializing the Module ```powershell # Initialize with default settings Initialize-WindowsNotifications -# Or initialize with a custom assembly path -Initialize-WindowsNotifications -AssemblyPath "C:\Path\To\WindowsNotifications.dll" - -# Or initialize with a custom database path +# Initialize with custom database path Initialize-WindowsNotifications -DatabasePath "C:\Path\To\Notifications.db" ``` -### Show Notifications +### Showing Notifications #### Simple Notification @@ -45,50 +40,71 @@ Show-Notification -Title "Hello" -Message "This is a simple notification" ```powershell $result = Show-Notification -Title "Action Required" -Message "Please select an option:" -Buttons "Approve", "Reject", "Defer" -if ($result.ClickedButtonText -eq "Approve") { - Write-Host "User approved the action" +# Check which button was clicked +if ($result.ClickedButtonId) { + Write-Host "Button clicked: $($result.ClickedButtonText)" } ``` -#### Reboot Notification with Deferrals +#### Reboot Notification ```powershell $result = Show-Notification -Title "System Reboot Required" -Message "Your system needs to be rebooted." -RebootButtonText "Reboot Now" -DeferButtonText "Defer" +# Check if the reboot button was clicked if ($result.ClickedButtonId -eq "reboot") { # Reboot the system Restart-Computer -Force } ``` -#### Advanced Options +#### Asynchronous Notification ```powershell -Show-Notification -Title "Advanced Notification" -Message "This notification has advanced options" ` - -Async -PersistState -TimeoutInSeconds 30 -LogoImagePath "C:\Path\To\Logo.png" ` - -HeroImagePath "C:\Path\To\Hero.png" -ShowReminder -ReminderTimeInMinutes 5 +$result = Show-Notification -Title "Background Task" -Message "A background task is running..." -Async + +# Do some work +# ... + +# Check if the notification has been interacted with +$currentResult = Get-NotificationResult -NotificationId $result.NotificationId +if ($currentResult.Activated) { + Write-Host "User clicked the notification" +} ``` -### Work with Notification Results +#### Notification with Deadline ```powershell -# Get the result of a notification -$result = Get-NotificationResult -NotificationId "notification-id" +$deadline = (Get-Date).AddMinutes(5) +$result = Show-Notification -Title "System Maintenance" -Message "Your system needs maintenance." -DeadlineTime $deadline -ShowCountdown + +# Check if the deadline was reached +if ($result.DeadlineReached) { + Write-Host "Deadline reached at $($result.DeadlineReachedTime)" +} +``` + +### Managing Notification Results + +```powershell +# Get a specific notification result +$result = Get-NotificationResult -NotificationId "12345678-1234-1234-1234-123456789012" # Wait for a notification to complete -$result = Wait-Notification -NotificationId "notification-id" -TimeoutInSeconds 30 +$result = Wait-Notification -NotificationId "12345678-1234-1234-1234-123456789012" -TimeoutInSeconds 30 -# Get all notification history -$history = Get-NotificationHistory +# Get all notification results +$results = Get-AllNotificationResults -# Remove notification history -Remove-NotificationHistory -NotificationId "notification-id" +# Remove a notification result +Remove-NotificationResult -NotificationId "12345678-1234-1234-1234-123456789012" -# Remove all notification history -Remove-NotificationHistory +# Clear all notification results +Clear-AllNotificationResults ``` -### System Information +### Utility Functions ```powershell # Check if running as SYSTEM @@ -98,127 +114,14 @@ $isSystem = Test-SystemContext $sessions = Get-InteractiveUserSessions ``` -## Command Reference +## Functions -| Command | Description | -| ------- | ----------- | -| `Initialize-WindowsNotifications` | Initializes the Windows Notifications module | -| `Show-Notification` | Shows a notification with various options | -| `Get-NotificationResult` | Gets the result of a notification | -| `Wait-Notification` | Waits for a notification to complete | -| `Get-NotificationHistory` | Gets all notification results from the database | -| `Remove-NotificationHistory` | Deletes notification results from the database | -| `Get-InteractiveUserSessions` | Gets all interactive user sessions | -| `Test-SystemContext` | Checks if the current process is running as SYSTEM | - -## Custom Branding - -The module supports custom branding for notifications, allowing you to create notifications that match your organization's branding: - -```powershell -Show-Notification -Title "IT Department Notification" -Message "System update required" ` - -BrandingText "Contoso IT" ` - -BrandingColor "#0078D7" ` - -AccentColor "#E81123" ` - -LogoImagePath "C:\Path\To\Logo.png" ` - -HeroImagePath "C:\Path\To\Banner.png" ` - -UseDarkTheme -``` - -### Supported Branding Options - -| Option | Description | -| ------ | ----------- | -| `BrandingText` | Custom branding text (e.g., company or department name) | -| `BrandingColor` | Custom branding color (hex format: #RRGGBB) | -| `AccentColor` | Custom accent color for the notification (hex format: #RRGGBB) | -| `UseDarkTheme` | Whether to use dark theme for the notification | -| `LogoImagePath` | Path or URL to a logo image | -| `HeroImagePath` | Path or URL to a hero/banner image | -| `InlineImagePath` | Path or URL to an inline image | -| `AppIconPath` | Path or URL to an app icon | -| `BackgroundImagePath` | Path or URL to a background image | -| `AudioSource` | Audio source for the notification | -| `SilentMode` | Whether to show the notification in silent mode (no sound) | -| `DeadlineTime` | Deadline time for the notification | -| `ShowCountdown` | Whether to show a countdown timer on the notification | -| `DeadlineActionCommand` | Command to execute when the deadline is reached | -| `DeadlineActionArguments` | Arguments for the deadline command | -| `DeadlineActionUrl` | URL to open when the deadline is reached | -| `DeadlineActionScript` | PowerShell script to execute when the deadline is reached | -| `EnableLogging` | Whether to enable logging for the notification | -| `LogFilePath` | Path to the log file - -## Examples - -### Example 1: Simple Notification - -```powershell -Import-Module WindowsNotifications -Initialize-WindowsNotifications - -$result = Show-Notification -Title "Hello" -Message "This is a simple notification" -Write-Host "Notification displayed: $($result.Displayed)" -``` - -### Example 2: Notification with Buttons - -```powershell -Import-Module WindowsNotifications -Initialize-WindowsNotifications - -$result = Show-Notification -Title "Action Required" -Message "Please select an option:" -Buttons "Approve", "Reject", "Defer" - -if ($result.ClickedButtonId) { - Write-Host "Button clicked: $($result.ClickedButtonText)" - - switch ($result.ClickedButtonText) { - "Approve" { Write-Host "User approved the action" } - "Reject" { Write-Host "User rejected the action" } - "Defer" { Write-Host "User deferred the action" } - } -} -``` - -### Example 3: Asynchronous Notification - -```powershell -Import-Module WindowsNotifications -Initialize-WindowsNotifications - -$result = Show-Notification -Title "Background Task" -Message "A background task is running" -Async - -# Do some work -for ($i = 1; $i -le 5; $i++) { - Write-Host "Working... ($i/5)" - Start-Sleep -Seconds 2 - - # Check if the notification has been interacted with - $currentResult = Get-NotificationResult -NotificationId $result.NotificationId - - if ($currentResult.Activated -or $currentResult.Dismissed) { - Write-Host "User interacted with the notification" - break - } -} - -Write-Host "Work completed" -``` - -### Example 4: Countdown and Deadline Notification - -```powershell -Import-Module WindowsNotifications -Initialize-WindowsNotifications - -# Create a notification with a deadline 5 minutes from now -$result = Show-Notification -Title "System Maintenance" -Message "Your system needs to restart soon." ` - -Buttons "Restart Now", "Defer" ` - -DeadlineTime (Get-Date).AddMinutes(5) ` - -ShowCountdown ` - -DeadlineActionScript "Restart-Computer -Force" ` - -EnableLogging ` - -LogFilePath "C:\Logs\notifications.log" - -Write-Host "Notification displayed with deadline: $($result.Displayed)" -``` +- `Initialize-WindowsNotifications` - Initializes the Windows Notifications module +- `Show-Notification` - Shows a notification +- `Get-NotificationResult` - Gets the result of a notification +- `Wait-Notification` - Waits for a notification to complete +- `Get-AllNotificationResults` - Gets all notification results +- `Remove-NotificationResult` - Removes a notification result +- `Clear-AllNotificationResults` - Clears all notification results +- `Test-SystemContext` - Checks if running as SYSTEM +- `Get-InteractiveUserSessions` - Gets interactive user sessions diff --git a/PowerShell/WindowsNotifications.psd1 b/PowerShell/WindowsNotifications.psd1 index 0ed1904..7be95f5 100644 --- a/PowerShell/WindowsNotifications.psd1 +++ b/PowerShell/WindowsNotifications.psd1 @@ -1,125 +1,70 @@ -# -# Module manifest for module 'WindowsNotifications' -# - @{ # Script module or binary module file associated with this manifest. RootModule = 'WindowsNotifications.psm1' - + # Version number of this module. ModuleVersion = '1.0.0' - - # Supported PSEditions - CompatiblePSEditions = @('Desktop') - + # ID used to uniquely identify this module - GUID = '8a1b3c4d-5e6f-47a8-b9c0-d1e2f3a4b5c6' - + GUID = '12345678-1234-1234-1234-123456789012' + # Author of this module - Author = 'WindowsNotifications' - + Author = 'Windows Notifications' + # Company or vendor of this module CompanyName = '' - + # Copyright statement for this module - Copyright = '(c) 2024. All rights reserved.' - + Copyright = '(c) 2023. All rights reserved.' + # Description of the functionality provided by this module - Description = 'PowerShell module for displaying Windows Toast Notifications from SYSTEM context to user sessions' - + Description = 'Windows Notifications for PowerShell' + # Minimum version of the Windows PowerShell engine required by this module PowerShellVersion = '5.0' - - # Name of the Windows PowerShell host required by this module - # PowerShellHostName = '' - - # Minimum version of the Windows PowerShell host required by this module - # PowerShellHostVersion = '' - - # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. - DotNetFrameworkVersion = '4.7.2' - - # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. - CLRVersion = '4.0' - - # Processor architecture (None, X86, Amd64) required by this module - # ProcessorArchitecture = '' - - # Modules that must be imported into the global environment prior to importing this module - # RequiredModules = @() - - # Assemblies that must be loaded prior to importing this module - # RequiredAssemblies = @() - - # Script files (.ps1) that are run in the caller's environment prior to importing this module. - # ScriptsToProcess = @() - - # Type files (.ps1xml) to be loaded when importing this module - # TypesToProcess = @() - - # Format files (.ps1xml) to be loaded when importing this module - # FormatsToProcess = @() - - # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess - # NestedModules = @() - - # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. + + # Functions to export from this module FunctionsToExport = @( 'Initialize-WindowsNotifications', 'Show-Notification', 'Get-NotificationResult', 'Wait-Notification', - 'Get-NotificationHistory', - 'Remove-NotificationHistory', - 'Get-InteractiveUserSessions', - 'Test-SystemContext' + 'Get-AllNotificationResults', + 'Remove-NotificationResult', + 'Clear-AllNotificationResults', + 'Test-SystemContext', + 'Get-InteractiveUserSessions' ) - - # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. + + # Cmdlets to export from this module CmdletsToExport = @() - + # Variables to export from this module - VariablesToExport = '*' - - # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. + VariablesToExport = @() + + # Aliases to export from this module AliasesToExport = @() - - # DSC resources to export from this module - # DscResourcesToExport = @() - - # List of all modules packaged with this module - # ModuleList = @() - - # List of all files packaged with this module - FileList = @( - 'WindowsNotifications.psm1', - 'WindowsNotifications.psd1', - 'WindowsNotifications.dll' - ) - - # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. + + # Assemblies that must be loaded prior to importing this module + RequiredAssemblies = @('WindowsNotifications.dll') + + # Private data to pass to the module specified in RootModule/ModuleToProcess PrivateData = @{ PSData = @{ # Tags applied to this module. These help with module discovery in online galleries. - Tags = @('Windows', 'Notifications', 'Toast', 'System') - + Tags = @('Windows', 'Notification', 'Toast') + # A URL to the license for this module. - LicenseUri = 'https://github.com/freedbygrace/WindowsNotifications/blob/main/LICENSE' - + LicenseUri = '' + # A URL to the main website for this project. - ProjectUri = 'https://github.com/freedbygrace/WindowsNotifications' - + ProjectUri = '' + # A URL to an icon representing this module. - # IconUri = '' - + IconUri = '' + # ReleaseNotes of this module - ReleaseNotes = 'Initial release of the WindowsNotifications module' + ReleaseNotes = 'Initial release of the Windows Notifications module.' } } - - # HelpInfo URI of this module - # HelpInfoURI = '' - - # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. - # DefaultCommandPrefix = '' } diff --git a/PowerShell/WindowsNotifications.psm1 b/PowerShell/WindowsNotifications.psm1 index c89c74a..cc4f71b 100644 --- a/PowerShell/WindowsNotifications.psm1 +++ b/PowerShell/WindowsNotifications.psm1 @@ -1,55 +1,12 @@ # # WindowsNotifications.psm1 -# PowerShell module for the Windows Notifications library +# PowerShell module for Windows notifications # +# The assembly is loaded automatically by the module manifest (PSD1) + # Module variables -$script:NotificationAssembly = $null $script:NotificationManager = $null -$script:DefaultDatabasePath = $null - -# -# Private functions -# - -function Initialize-NotificationAssembly { - [CmdletBinding()] - param ( - [Parameter(Mandatory=$false)] - [string]$AssemblyPath - ) - - try { - # If assembly path is provided and exists, load from file - if ($AssemblyPath -and (Test-Path $AssemblyPath)) { - $bytes = [System.IO.File]::ReadAllBytes($AssemblyPath) - $script:NotificationAssembly = [System.Reflection.Assembly]::Load($bytes) - } - # Otherwise, try to load from the module directory - else { - $moduleRoot = Split-Path -Parent $PSCommandPath - $defaultPath = Join-Path -Path $moduleRoot -ChildPath "WindowsNotifications.dll" - - if (Test-Path $defaultPath) { - $bytes = [System.IO.File]::ReadAllBytes($defaultPath) - $script:NotificationAssembly = [System.Reflection.Assembly]::Load($bytes) - } - else { - throw "WindowsNotifications.dll not found. Please specify the path using the -AssemblyPath parameter." - } - } - - # Create the notification manager - $script:NotificationManager = New-Object WindowsNotifications.NotificationManager - $script:DefaultDatabasePath = $script:NotificationManager.GetDatabaseFilePath() - - return $true - } - catch { - Write-Error "Failed to initialize WindowsNotifications assembly: $_" - return $false - } -} # # Public functions @@ -58,42 +15,39 @@ function Initialize-NotificationAssembly { function Initialize-WindowsNotifications { [CmdletBinding()] param ( - [Parameter(Mandatory=$false)] - [string]$AssemblyPath, - [Parameter(Mandatory=$false)] [string]$DatabasePath ) - # Initialize the assembly - if (-not (Initialize-NotificationAssembly -AssemblyPath $AssemblyPath)) { + try { + # Create the notification manager + if ($DatabasePath) { + $script:NotificationManager = New-Object WindowsNotifications.NotificationManager($DatabasePath) + } + else { + $script:NotificationManager = New-Object WindowsNotifications.NotificationManager + } + + Write-Output "Windows Notifications initialized successfully." + Write-Output "Database path: $($script:NotificationManager.GetDatabaseFilePath())" + + # Check if running as SYSTEM + $isSystem = $script:NotificationManager.IsRunningAsSystem() + Write-Output "Running as SYSTEM: $isSystem" + + # Check for interactive user sessions + $sessions = $script:NotificationManager.GetInteractiveUserSessions() + Write-Output "Interactive user sessions: $($sessions.Count)" + foreach ($session in $sessions) { + Write-Output " - $session" + } + + return $true + } + catch { + Write-Error "Failed to initialize NotificationManager: $_" return $false } - - # If a custom database path is specified, create a new notification manager with that path - if ($DatabasePath) { - try { - $script:NotificationManager = New-Object WindowsNotifications.NotificationManager($DatabasePath) - $script:DefaultDatabasePath = $script:NotificationManager.GetDatabaseFilePath() - } - catch { - Write-Error "Failed to initialize NotificationManager with custom database path: $_" - return $false - } - } - - Write-Host "WindowsNotifications initialized successfully." - Write-Host "Database path: $script:DefaultDatabasePath" - - # Check if running as SYSTEM - $isSystem = $script:NotificationManager.IsRunningAsSystem() - Write-Host "Running as SYSTEM: $isSystem" - - # Get interactive user sessions - $sessions = $script:NotificationManager.GetInteractiveUserSessions() - Write-Host "Interactive user sessions found: $($sessions.Count)" - - return $true } function Show-Notification { @@ -112,22 +66,11 @@ function Show-Notification { [Parameter(Mandatory=$true, ParameterSetName="WithButtons")] [string[]]$Buttons, - [Parameter(Mandatory=$false, ParameterSetName="Reboot")] - [string]$RebootButtonText = "Reboot Now", - - [Parameter(Mandatory=$false, ParameterSetName="Reboot")] - [string]$DeferButtonText = "Defer", - [Parameter(Mandatory=$false, ParameterSetName="Simple")] [Parameter(Mandatory=$false, ParameterSetName="WithButtons")] [Parameter(Mandatory=$false, ParameterSetName="Reboot")] [switch]$Async, - [Parameter(Mandatory=$false, ParameterSetName="Simple")] - [Parameter(Mandatory=$false, ParameterSetName="WithButtons")] - [Parameter(Mandatory=$false, ParameterSetName="Reboot")] - [switch]$PersistState, - [Parameter(Mandatory=$false, ParameterSetName="Simple")] [Parameter(Mandatory=$false, ParameterSetName="WithButtons")] [Parameter(Mandatory=$false, ParameterSetName="Reboot")] @@ -146,57 +89,7 @@ function Show-Notification { [Parameter(Mandatory=$false, ParameterSetName="Simple")] [Parameter(Mandatory=$false, ParameterSetName="WithButtons")] [Parameter(Mandatory=$false, ParameterSetName="Reboot")] - [string]$InlineImagePath, - - [Parameter(Mandatory=$false, ParameterSetName="Simple")] - [Parameter(Mandatory=$false, ParameterSetName="WithButtons")] - [Parameter(Mandatory=$false, ParameterSetName="Reboot")] - [string]$AppIconPath, - - [Parameter(Mandatory=$false, ParameterSetName="Simple")] - [Parameter(Mandatory=$false, ParameterSetName="WithButtons")] - [Parameter(Mandatory=$false, ParameterSetName="Reboot")] - [string]$BackgroundImagePath, - - [Parameter(Mandatory=$false, ParameterSetName="Simple")] - [Parameter(Mandatory=$false, ParameterSetName="WithButtons")] - [Parameter(Mandatory=$false, ParameterSetName="Reboot")] - [string]$BrandingText, - - [Parameter(Mandatory=$false, ParameterSetName="Simple")] - [Parameter(Mandatory=$false, ParameterSetName="WithButtons")] - [Parameter(Mandatory=$false, ParameterSetName="Reboot")] - [string]$BrandingColor, - - [Parameter(Mandatory=$false, ParameterSetName="Simple")] - [Parameter(Mandatory=$false, ParameterSetName="WithButtons")] - [Parameter(Mandatory=$false, ParameterSetName="Reboot")] - [string]$AccentColor, - - [Parameter(Mandatory=$false, ParameterSetName="Simple")] - [Parameter(Mandatory=$false, ParameterSetName="WithButtons")] - [Parameter(Mandatory=$false, ParameterSetName="Reboot")] - [switch]$UseDarkTheme, - - [Parameter(Mandatory=$false, ParameterSetName="Simple")] - [Parameter(Mandatory=$false, ParameterSetName="WithButtons")] - [Parameter(Mandatory=$false, ParameterSetName="Reboot")] - [string]$AudioSource, - - [Parameter(Mandatory=$false, ParameterSetName="Simple")] - [Parameter(Mandatory=$false, ParameterSetName="WithButtons")] - [Parameter(Mandatory=$false, ParameterSetName="Reboot")] - [switch]$SilentMode, - - [Parameter(Mandatory=$false, ParameterSetName="Simple")] - [Parameter(Mandatory=$false, ParameterSetName="WithButtons")] - [Parameter(Mandatory=$false, ParameterSetName="Reboot")] - [switch]$ShowReminder, - - [Parameter(Mandatory=$false, ParameterSetName="Simple")] - [Parameter(Mandatory=$false, ParameterSetName="WithButtons")] - [Parameter(Mandatory=$false, ParameterSetName="Reboot")] - [int]$ReminderTimeInMinutes = 60, + [string]$Attribution, [Parameter(Mandatory=$false, ParameterSetName="Simple")] [Parameter(Mandatory=$false, ParameterSetName="WithButtons")] @@ -208,38 +101,14 @@ function Show-Notification { [Parameter(Mandatory=$false, ParameterSetName="Reboot")] [switch]$ShowCountdown, - [Parameter(Mandatory=$false, ParameterSetName="Simple")] - [Parameter(Mandatory=$false, ParameterSetName="WithButtons")] [Parameter(Mandatory=$false, ParameterSetName="Reboot")] - [string]$DeadlineActionCommand, + [string]$RebootButtonText = "Reboot Now", - [Parameter(Mandatory=$false, ParameterSetName="Simple")] - [Parameter(Mandatory=$false, ParameterSetName="WithButtons")] [Parameter(Mandatory=$false, ParameterSetName="Reboot")] - [string]$DeadlineActionArguments, - - [Parameter(Mandatory=$false, ParameterSetName="Simple")] - [Parameter(Mandatory=$false, ParameterSetName="WithButtons")] - [Parameter(Mandatory=$false, ParameterSetName="Reboot")] - [string]$DeadlineActionUrl, - - [Parameter(Mandatory=$false, ParameterSetName="Simple")] - [Parameter(Mandatory=$false, ParameterSetName="WithButtons")] - [Parameter(Mandatory=$false, ParameterSetName="Reboot")] - [string]$DeadlineActionScript, - - [Parameter(Mandatory=$false, ParameterSetName="Simple")] - [Parameter(Mandatory=$false, ParameterSetName="WithButtons")] - [Parameter(Mandatory=$false, ParameterSetName="Reboot")] - [switch]$EnableLogging, - - [Parameter(Mandatory=$false, ParameterSetName="Simple")] - [Parameter(Mandatory=$false, ParameterSetName="WithButtons")] - [Parameter(Mandatory=$false, ParameterSetName="Reboot")] - [string]$LogFilePath + [string]$DeferButtonText = "Defer" ) - # Ensure the notification assembly is initialized + # Ensure the notification manager is initialized if (-not $script:NotificationManager) { if (-not (Initialize-WindowsNotifications)) { return $null @@ -247,129 +116,50 @@ function Show-Notification { } try { + # Create notification options + $options = New-Object WindowsNotifications.Models.NotificationOptions + $options.Title = $Title + $options.Message = $Message + $options.Async = $Async.IsPresent + $options.TimeoutInSeconds = $TimeoutInSeconds + + # Add optional parameters + if ($LogoImagePath) { $options.LogoImagePath = $LogoImagePath } + if ($HeroImagePath) { $options.HeroImagePath = $HeroImagePath } + if ($Attribution) { $options.Attribution = $Attribution } + if ($DeadlineTime) { $options.DeadlineTime = $DeadlineTime } + if ($ShowCountdown) { $options.ShowCountdown = $true } + # Handle different parameter sets switch ($PSCmdlet.ParameterSetName) { "Simple" { - # Create custom notification options for simple notification - $options = New-Object WindowsNotifications.Models.NotificationOptions - $options.Title = $Title - $options.Message = $Message - $options.Async = $Async - $options.PersistState = $PersistState - $options.TimeoutInSeconds = $TimeoutInSeconds - $options.ShowReminder = $ShowReminder - $options.ReminderTimeInMinutes = $ReminderTimeInMinutes - - # Set image paths - if ($LogoImagePath) { $options.LogoImagePath = $LogoImagePath } - if ($HeroImagePath) { $options.HeroImagePath = $HeroImagePath } - if ($InlineImagePath) { $options.InlineImagePath = $InlineImagePath } - if ($AppIconPath) { $options.AppIconPath = $AppIconPath } - if ($BackgroundImagePath) { $options.BackgroundImagePath = $BackgroundImagePath } - - # Set branding options - if ($BrandingText) { $options.BrandingText = $BrandingText } - if ($BrandingColor) { $options.BrandingColor = $BrandingColor } - if ($AccentColor) { $options.AccentColor = $AccentColor } - if ($UseDarkTheme) { $options.UseDarkTheme = $UseDarkTheme } - - # Set audio options - if ($AudioSource) { $options.AudioSource = $AudioSource } - if ($SilentMode) { $options.SilentMode = $SilentMode } - - # Set deadline and countdown options - if ($DeadlineTime -ne $null) { $options.DeadlineTime = $DeadlineTime } - if ($ShowCountdown) { $options.ShowCountdown = $ShowCountdown } - - # Set deadline action - if ($DeadlineActionCommand) { - $options.DeadlineAction = New-Object WindowsNotifications.Models.DeadlineAction($DeadlineActionCommand, $DeadlineActionArguments) - } - elseif ($DeadlineActionUrl) { - $options.DeadlineAction = [WindowsNotifications.Models.DeadlineAction]::OpenUrl($DeadlineActionUrl) - } - elseif ($DeadlineActionScript) { - $options.DeadlineAction = [WindowsNotifications.Models.DeadlineAction]::ExecuteScript($DeadlineActionScript) - } - - # Set logging options - if ($EnableLogging) { $options.EnableLogging = $true } - if ($LogFilePath) { - $options.LogAction = { - param($logEntry) - Add-Content -Path $LogFilePath -Value $logEntry - } - } - - $result = $script:NotificationManager.ShowNotification($options) + # Show a simple notification + return $script:NotificationManager.ShowNotification($options) } "WithButtons" { - # Create custom notification options for notification with buttons - $options = New-Object WindowsNotifications.Models.NotificationOptions - $options.Title = $Title - $options.Message = $Message - $options.Async = $Async - $options.PersistState = $PersistState - $options.TimeoutInSeconds = $TimeoutInSeconds - $options.ShowReminder = $ShowReminder - $options.ReminderTimeInMinutes = $ReminderTimeInMinutes - - # Set image paths - if ($LogoImagePath) { $options.LogoImagePath = $LogoImagePath } - if ($HeroImagePath) { $options.HeroImagePath = $HeroImagePath } - if ($InlineImagePath) { $options.InlineImagePath = $InlineImagePath } - if ($AppIconPath) { $options.AppIconPath = $AppIconPath } - if ($BackgroundImagePath) { $options.BackgroundImagePath = $BackgroundImagePath } - - # Set branding options - if ($BrandingText) { $options.BrandingText = $BrandingText } - if ($BrandingColor) { $options.BrandingColor = $BrandingColor } - if ($AccentColor) { $options.AccentColor = $AccentColor } - if ($UseDarkTheme) { $options.UseDarkTheme = $UseDarkTheme } - - # Set audio options - if ($AudioSource) { $options.AudioSource = $AudioSource } - if ($SilentMode) { $options.SilentMode = $SilentMode } - - # Set deadline and countdown options - if ($DeadlineTime -ne $null) { $options.DeadlineTime = $DeadlineTime } - if ($ShowCountdown) { $options.ShowCountdown = $ShowCountdown } - - # Set deadline action - if ($DeadlineActionCommand) { - $options.DeadlineAction = New-Object WindowsNotifications.Models.DeadlineAction($DeadlineActionCommand, $DeadlineActionArguments) - } - elseif ($DeadlineActionUrl) { - $options.DeadlineAction = [WindowsNotifications.Models.DeadlineAction]::OpenUrl($DeadlineActionUrl) - } - elseif ($DeadlineActionScript) { - $options.DeadlineAction = [WindowsNotifications.Models.DeadlineAction]::ExecuteScript($DeadlineActionScript) - } - - # Set logging options - if ($EnableLogging) { $options.EnableLogging = $true } - if ($LogFilePath) { - $options.LogAction = { - param($logEntry) - Add-Content -Path $LogFilePath -Value $logEntry - } - } - # Add buttons foreach ($buttonText in $Buttons) { - $button = New-Object WindowsNotifications.Models.NotificationButton($buttonText) + $button = New-Object WindowsNotifications.Models.NotificationButton($buttonText, "button$($options.Buttons.Count)") $options.Buttons.Add($button) } - $result = $script:NotificationManager.ShowNotification($options) + # Show the notification with buttons + return $script:NotificationManager.ShowNotification($options) } "Reboot" { - # Use the built-in reboot notification method - $result = $script:NotificationManager.ShowRebootNotification($Title, $Message, $RebootButtonText, $DeferButtonText) + # Create deferral options + $deferralOptions = New-Object WindowsNotifications.Models.DeferralOptions + $deferralOptions.DeferButtonText = $DeferButtonText + $options.DeferralOptions = $deferralOptions + + # Add reboot button + $rebootButton = New-Object WindowsNotifications.Models.NotificationButton($RebootButtonText, "reboot") + $options.Buttons.Add($rebootButton) + + # Show the reboot notification + return $script:NotificationManager.ShowNotification($options) } } - - return $result } catch { Write-Error "Failed to show notification: $_" @@ -384,7 +174,7 @@ function Get-NotificationResult { [string]$NotificationId ) - # Ensure the notification assembly is initialized + # Ensure the notification manager is initialized if (-not $script:NotificationManager) { if (-not (Initialize-WindowsNotifications)) { return $null @@ -410,7 +200,7 @@ function Wait-Notification { [int]$TimeoutInSeconds = -1 ) - # Ensure the notification assembly is initialized + # Ensure the notification manager is initialized if (-not $script:NotificationManager) { if (-not (Initialize-WindowsNotifications)) { return $null @@ -418,8 +208,7 @@ function Wait-Notification { } try { - $timeoutMs = $TimeoutInSeconds -eq -1 ? -1 : ($TimeoutInSeconds * 1000) - return $script:NotificationManager.WaitForNotification($NotificationId, $timeoutMs) + return $script:NotificationManager.WaitForNotification($NotificationId, $TimeoutInSeconds * 1000) } catch { Write-Error "Failed to wait for notification: $_" @@ -427,11 +216,11 @@ function Wait-Notification { } } -function Get-NotificationHistory { +function Get-AllNotificationResults { [CmdletBinding()] param () - # Ensure the notification assembly is initialized + # Ensure the notification manager is initialized if (-not $script:NotificationManager) { if (-not (Initialize-WindowsNotifications)) { return $null @@ -442,19 +231,19 @@ function Get-NotificationHistory { return $script:NotificationManager.GetAllNotificationResults() } catch { - Write-Error "Failed to get notification history: $_" + Write-Error "Failed to get all notification results: $_" return $null } } -function Remove-NotificationHistory { +function Remove-NotificationResult { [CmdletBinding()] param ( - [Parameter(Mandatory=$false)] + [Parameter(Mandatory=$true)] [string]$NotificationId ) - # Ensure the notification assembly is initialized + # Ensure the notification manager is initialized if (-not $script:NotificationManager) { if (-not (Initialize-WindowsNotifications)) { return $false @@ -462,36 +251,31 @@ function Remove-NotificationHistory { } try { - if ($NotificationId) { - return $script:NotificationManager.DeleteNotificationResult($NotificationId) - } - else { - return $script:NotificationManager.DeleteAllNotificationResults() - } + return $script:NotificationManager.DeleteNotificationResult($NotificationId) } catch { - Write-Error "Failed to remove notification history: $_" + Write-Error "Failed to remove notification result: $_" return $false } } -function Get-InteractiveUserSessions { +function Clear-AllNotificationResults { [CmdletBinding()] param () - # Ensure the notification assembly is initialized + # Ensure the notification manager is initialized if (-not $script:NotificationManager) { if (-not (Initialize-WindowsNotifications)) { - return $null + return $false } } try { - return $script:NotificationManager.GetInteractiveUserSessions() + return $script:NotificationManager.DeleteAllNotificationResults() } catch { - Write-Error "Failed to get interactive user sessions: $_" - return $null + Write-Error "Failed to clear all notification results: $_" + return $false } } @@ -499,7 +283,7 @@ function Test-SystemContext { [CmdletBinding()] param () - # Ensure the notification assembly is initialized + # Ensure the notification manager is initialized if (-not $script:NotificationManager) { if (-not (Initialize-WindowsNotifications)) { return $false @@ -515,5 +299,25 @@ function Test-SystemContext { } } +function Get-InteractiveUserSessions { + [CmdletBinding()] + param () + + # Ensure the notification manager is initialized + if (-not $script:NotificationManager) { + if (-not (Initialize-WindowsNotifications)) { + return $null + } + } + + try { + return $script:NotificationManager.GetInteractiveUserSessions() + } + catch { + Write-Error "Failed to get interactive user sessions: $_" + return $null + } +} + # Export public functions -Export-ModuleMember -Function Initialize-WindowsNotifications, Show-Notification, Get-NotificationResult, Wait-Notification, Get-NotificationHistory, Remove-NotificationHistory, Get-InteractiveUserSessions, Test-SystemContext +Export-ModuleMember -Function Initialize-WindowsNotifications, Show-Notification, Get-NotificationResult, Wait-Notification, Get-AllNotificationResults, Remove-NotificationResult, Clear-AllNotificationResults, Test-SystemContext, Get-InteractiveUserSessions