Files
WindowsNotifications/PowerShell/WindowsNotifications.psm1
T
GraceSolutions 2a80e82288 First Commit
2025-04-10 16:01:19 -04:00

520 lines
19 KiB
PowerShell

#
# WindowsNotifications.psm1
# PowerShell module for the Windows Notifications library
#
# 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
#
function Initialize-WindowsNotifications {
[CmdletBinding()]
param (
[Parameter(Mandatory=$false)]
[string]$AssemblyPath,
[Parameter(Mandatory=$false)]
[string]$DatabasePath
)
# Initialize the assembly
if (-not (Initialize-NotificationAssembly -AssemblyPath $AssemblyPath)) {
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 {
[CmdletBinding(DefaultParameterSetName="Simple")]
param (
[Parameter(Mandatory=$true, ParameterSetName="Simple")]
[Parameter(Mandatory=$true, ParameterSetName="WithButtons")]
[Parameter(Mandatory=$true, ParameterSetName="Reboot")]
[string]$Title,
[Parameter(Mandatory=$true, ParameterSetName="Simple")]
[Parameter(Mandatory=$true, ParameterSetName="WithButtons")]
[Parameter(Mandatory=$true, ParameterSetName="Reboot")]
[string]$Message,
[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")]
[int]$TimeoutInSeconds = 0,
[Parameter(Mandatory=$false, ParameterSetName="Simple")]
[Parameter(Mandatory=$false, ParameterSetName="WithButtons")]
[Parameter(Mandatory=$false, ParameterSetName="Reboot")]
[string]$LogoImagePath,
[Parameter(Mandatory=$false, ParameterSetName="Simple")]
[Parameter(Mandatory=$false, ParameterSetName="WithButtons")]
[Parameter(Mandatory=$false, ParameterSetName="Reboot")]
[string]$HeroImagePath,
[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,
[Parameter(Mandatory=$false, ParameterSetName="Simple")]
[Parameter(Mandatory=$false, ParameterSetName="WithButtons")]
[Parameter(Mandatory=$false, ParameterSetName="Reboot")]
[DateTime]$DeadlineTime,
[Parameter(Mandatory=$false, ParameterSetName="Simple")]
[Parameter(Mandatory=$false, ParameterSetName="WithButtons")]
[Parameter(Mandatory=$false, ParameterSetName="Reboot")]
[switch]$ShowCountdown,
[Parameter(Mandatory=$false, ParameterSetName="Simple")]
[Parameter(Mandatory=$false, ParameterSetName="WithButtons")]
[Parameter(Mandatory=$false, ParameterSetName="Reboot")]
[string]$DeadlineActionCommand,
[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
)
# Ensure the notification assembly is initialized
if (-not $script:NotificationManager) {
if (-not (Initialize-WindowsNotifications)) {
return $null
}
}
try {
# 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)
}
"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)
$options.Buttons.Add($button)
}
$result = $script:NotificationManager.ShowNotification($options)
}
"Reboot" {
# Use the built-in reboot notification method
$result = $script:NotificationManager.ShowRebootNotification($Title, $Message, $RebootButtonText, $DeferButtonText)
}
}
return $result
}
catch {
Write-Error "Failed to show notification: $_"
return $null
}
}
function Get-NotificationResult {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[string]$NotificationId
)
# Ensure the notification assembly is initialized
if (-not $script:NotificationManager) {
if (-not (Initialize-WindowsNotifications)) {
return $null
}
}
try {
return $script:NotificationManager.GetNotificationResult($NotificationId)
}
catch {
Write-Error "Failed to get notification result: $_"
return $null
}
}
function Wait-Notification {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[string]$NotificationId,
[Parameter(Mandatory=$false)]
[int]$TimeoutInSeconds = -1
)
# Ensure the notification assembly is initialized
if (-not $script:NotificationManager) {
if (-not (Initialize-WindowsNotifications)) {
return $null
}
}
try {
$timeoutMs = $TimeoutInSeconds -eq -1 ? -1 : ($TimeoutInSeconds * 1000)
return $script:NotificationManager.WaitForNotification($NotificationId, $timeoutMs)
}
catch {
Write-Error "Failed to wait for notification: $_"
return $null
}
}
function Get-NotificationHistory {
[CmdletBinding()]
param ()
# Ensure the notification assembly is initialized
if (-not $script:NotificationManager) {
if (-not (Initialize-WindowsNotifications)) {
return $null
}
}
try {
return $script:NotificationManager.GetAllNotificationResults()
}
catch {
Write-Error "Failed to get notification history: $_"
return $null
}
}
function Remove-NotificationHistory {
[CmdletBinding()]
param (
[Parameter(Mandatory=$false)]
[string]$NotificationId
)
# Ensure the notification assembly is initialized
if (-not $script:NotificationManager) {
if (-not (Initialize-WindowsNotifications)) {
return $false
}
}
try {
if ($NotificationId) {
return $script:NotificationManager.DeleteNotificationResult($NotificationId)
}
else {
return $script:NotificationManager.DeleteAllNotificationResults()
}
}
catch {
Write-Error "Failed to remove notification history: $_"
return $false
}
}
function Get-InteractiveUserSessions {
[CmdletBinding()]
param ()
# Ensure the notification assembly 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
}
}
function Test-SystemContext {
[CmdletBinding()]
param ()
# Ensure the notification assembly is initialized
if (-not $script:NotificationManager) {
if (-not (Initialize-WindowsNotifications)) {
return $false
}
}
try {
return $script:NotificationManager.IsRunningAsSystem()
}
catch {
Write-Error "Failed to check system context: $_"
return $false
}
}
# Export public functions
Export-ModuleMember -Function Initialize-WindowsNotifications, Show-Notification, Get-NotificationResult, Wait-Notification, Get-NotificationHistory, Remove-NotificationHistory, Get-InteractiveUserSessions, Test-SystemContext