modules/windows_integration.ps1
|
<#
.SYNOPSIS PSConsoleUI - Windows Native Integration .DESCRIPTION Provides integration with native Windows APIs (Taskbar, Notifications, etc.) Uses embedded C# types for interaction with Windows Shell. #> # 1. C# Type Definition for Taskbar & Toast # We use Add-Type to inject the necessary definitions if they don't exist $code = @" using System; using System.Runtime.InteropServices; namespace Hermes.Native { [ComImport] [Guid("56FDF342-FD6D-11d0-958A-006097C9A090")] [ClassInterface(ClassInterfaceType.None)] public class TaskbarList { } [ComImport] [Guid("ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface ITaskbarList3 { // ITaskbarList void HrInit(); void AddTab(IntPtr hwnd); void DeleteTab(IntPtr hwnd); void ActivateTab(IntPtr hwnd); void SetActiveAlt(IntPtr hwnd); // ITaskbarList2 void MarkFullscreenWindow(IntPtr hwnd, bool fFullscreen); // ITaskbarList3 void SetProgressValue(IntPtr hwnd, ulong ullCompleted, ulong ullTotal); void SetProgressState(IntPtr hwnd, int tbpFlags); void RegisterTab(IntPtr hwndTab, IntPtr hwndMDI); void UnregisterTab(IntPtr hwndTab); void SetTabOrder(IntPtr hwndTab, IntPtr hwndInsertBefore); void SetTabActive(IntPtr hwndTab, IntPtr hwndMDI, int dwReserved); void ThumbBarAddButtons(IntPtr hwnd, uint cButtons, IntPtr pButton); void ThumbBarUpdateButtons(IntPtr hwnd, uint cButtons, IntPtr pButton); void ThumbBarSetImageList(IntPtr hwnd, IntPtr himl); void SetOverlayIcon(IntPtr hwnd, IntPtr hIcon, string pszDescription); void SetThumbnailTooltip(IntPtr hwnd, string pszTip); void SetThumbnailClip(IntPtr hwnd, IntPtr prcClip); } } "@ try { if (-not ([System.Management.Automation.PSTypeName]'Hermes.Native.TaskbarList').Type) { Add-Type -TypeDefinition $code -ErrorAction Stop } } catch { # Fail silently on non-Windows or restricted environments # Write-Warning "Windows Native Integration not available." } # Enum for Taskbar States $TBPF_NOPROGRESS = 0 $TBPF_INDETERMINATE = 0x1 $TBPF_NORMAL = 0x2 $TBPF_ERROR = 0x4 $TBPF_PAUSED = 0x8 # Global standard wrapper function Set-TaskbarProgress { <# .SYNOPSIS Sets the progress bar state on the taskbar icon. .PARAMETER State Normal, Error, Paused, Indeterminate, None .PARAMETER Value Progress value (0-100) #> param( [ValidateSet('Normal','Error','Paused','Indeterminate','None')] [string]$State = 'Normal', [int]$Value = 0, [int]$Max = 100 ) # Needs console handle $hwnd = (Get-Process -Id $PID).MainWindowHandle if ($hwnd -eq 0) { return } try { $tb = [Hermes.Native.TaskbarList]::new() $tbi = $tb -as [Hermes.Native.ITaskbarList3] # Calculate Flag $flag = switch ($State) { 'None' { 0 } 'Indeterminate' { 0x1 } 'Normal' { 0x2 } 'Error' { 0x4 } 'Paused' { 0x8 } } $tbi.SetProgressState($hwnd, $flag) if ($State -in @('Normal','Error','Paused')) { $tbi.SetProgressValue($hwnd, [ulong]$Value, [ulong]$Max) } } catch { # Ignore COM errors } } function Show-WindowsNotification { <# .SYNOPSIS Displays a native Windows Toast Notification. #> param( [string]$Title, [string]$Message, [string]$IconPath # Optional ) # Use PowerShell's built-in BurntToast-like method via .NET or simple balloon fallback # For vanilla dependency-free, we can use the NotifyIcon trick or just rely on # System.Windows.Forms if available (older style) or WinRT (harder from PS plain). # Fallback: Powershell BurntToast module is best, but we want zero-dep. # We will use the System.Windows.Forms NotifyIcon for "Tray Balloon" which is simpler # and works on older servers too. For true Toasts we need XML, which is verbose. Add-Type -AssemblyName System.Windows.Forms $notify = New-Object System.Windows.Forms.NotifyIcon $notify.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon((Get-Process -Id $PID).Path) $notify.Visible = $true $notify.ShowBalloonTip(10000, $Title, $Message, [System.Windows.Forms.ToolTipIcon]::Info) # Cleanup after a bit start-sleep -milliseconds 100 $notify.Dispose() } Export-ModuleMember -Function Set-TaskbarProgress, Show-WindowsNotification |