Last active
September 9, 2025 01:58
-
-
Save jeffreyschultz/e4b6c583b86517ab6ddbfe3f7064be56 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #Requires -Version 5.1 | |
| <# | |
| .SYNOPSIS | |
| Off-Screen Window Recovery Module | |
| .DESCRIPTION | |
| A PowerShell module that provides functionality to detect and recover windows that have | |
| become positioned off-screen, typically after disconnecting external monitors or changing | |
| display configurations. This is especially useful for picture-in-picture windows, | |
| floating toolbars, and other windows that can get "lost" outside the visible desktop area. | |
| .AUTHOR | |
| Jeffrey Schultz <jeffrey@schultz.mx> | |
| .VERSION | |
| 1.0.0 | |
| .NOTES | |
| This module uses Windows API calls to enumerate and reposition windows. | |
| Requires Windows operating system. | |
| .EXAMPLE | |
| Import-Module .\OffScreenWindowRecovery.psm1 | |
| Repair-OffScreenWindows | |
| .EXAMPLE | |
| Import-Module .\OffScreenWindowRecovery.psm1 | |
| Get-OffScreenWindows -Verbose | |
| Repair-OffScreenWindows -ProcessName "vivaldi" -Verbose | |
| #> | |
| # Windows API definitions - only add if not already defined | |
| if (-not ('WindowAPI' -as [type])) { | |
| Add-Type -TypeDefinition @" | |
| using System; | |
| using System.Runtime.InteropServices; | |
| using System.Text; | |
| public struct RECT { | |
| public int left; | |
| public int top; | |
| public int right; | |
| public int bottom; | |
| } | |
| public struct POINT { | |
| public int x; | |
| public int y; | |
| } | |
| public static class WindowAPI { | |
| [DllImport("user32.dll")] | |
| public static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam); | |
| [DllImport("user32.dll")] | |
| public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); | |
| [DllImport("user32.dll")] | |
| public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); | |
| [DllImport("user32.dll")] | |
| public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); | |
| [DllImport("user32.dll")] | |
| public static extern int GetWindowTextLength(IntPtr hWnd); | |
| [DllImport("user32.dll")] | |
| public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); | |
| [DllImport("user32.dll")] | |
| public static extern bool IsWindowVisible(IntPtr hWnd); | |
| [DllImport("user32.dll")] | |
| public static extern bool IsIconic(IntPtr hWnd); | |
| [DllImport("user32.dll")] | |
| public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); | |
| [DllImport("user32.dll")] | |
| public static extern bool SetForegroundWindow(IntPtr hWnd); | |
| [DllImport("user32.dll")] | |
| public static extern int GetSystemMetrics(int nIndex); | |
| public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); | |
| // SetWindowPos flags | |
| public const uint SWP_NOSIZE = 0x0001; | |
| public const uint SWP_NOZORDER = 0x0004; | |
| public const uint SWP_SHOWWINDOW = 0x0040; | |
| public const uint SWP_FRAMECHANGED = 0x0020; | |
| // ShowWindow commands | |
| public const int SW_RESTORE = 9; | |
| public const int SW_SHOW = 5; | |
| // System metrics | |
| public const int SM_CXSCREEN = 0; | |
| public const int SM_CYSCREEN = 1; | |
| public const int SM_CXVIRTUALSCREEN = 78; | |
| public const int SM_CYVIRTUALSCREEN = 79; | |
| public const int SM_XVIRTUALSCREEN = 76; | |
| public const int SM_YVIRTUALSCREEN = 77; | |
| } | |
| "@ | |
| } | |
| # Internal helper function to get screen information | |
| function Get-ScreenInformation { | |
| [CmdletBinding()] | |
| param() | |
| try { | |
| # Try to use Windows Forms for accurate screen info | |
| Add-Type -AssemblyName System.Windows.Forms -ErrorAction SilentlyContinue | |
| $primaryScreen = [System.Windows.Forms.Screen]::PrimaryScreen | |
| $allScreens = [System.Windows.Forms.Screen]::AllScreens | |
| $screenInfo = @{ | |
| Primary = @{ | |
| Width = $primaryScreen.Bounds.Width | |
| Height = $primaryScreen.Bounds.Height | |
| Left = $primaryScreen.Bounds.Left | |
| Top = $primaryScreen.Bounds.Top | |
| } | |
| Virtual = @{ | |
| Width = ($allScreens | Measure-Object -Property {$_.Bounds.Width} -Sum).Sum | |
| Height = ($allScreens | Measure-Object -Property {$_.Bounds.Height} -Maximum).Maximum | |
| Left = ($allScreens | Measure-Object -Property {$_.Bounds.Left} -Minimum).Minimum | |
| Top = ($allScreens | Measure-Object -Property {$_.Bounds.Top} -Minimum).Minimum | |
| } | |
| AllScreens = $allScreens | ForEach-Object { | |
| @{ | |
| Width = $_.Bounds.Width | |
| Height = $_.Bounds.Height | |
| Left = $_.Bounds.Left | |
| Top = $_.Bounds.Top | |
| IsPrimary = $_.Primary | |
| DeviceName = $_.DeviceName | |
| } | |
| } | |
| } | |
| } | |
| catch { | |
| # Fallback to Windows API | |
| $screenInfo = @{ | |
| Primary = @{ | |
| Width = [WindowAPI]::GetSystemMetrics([WindowAPI]::SM_CXSCREEN) | |
| Height = [WindowAPI]::GetSystemMetrics([WindowAPI]::SM_CYSCREEN) | |
| Left = 0 | |
| Top = 0 | |
| } | |
| Virtual = @{ | |
| Width = [WindowAPI]::GetSystemMetrics([WindowAPI]::SM_CXVIRTUALSCREEN) | |
| Height = [WindowAPI]::GetSystemMetrics([WindowAPI]::SM_CYVIRTUALSCREEN) | |
| Left = [WindowAPI]::GetSystemMetrics([WindowAPI]::SM_XVIRTUALSCREEN) | |
| Top = [WindowAPI]::GetSystemMetrics([WindowAPI]::SM_YVIRTUALSCREEN) | |
| } | |
| AllScreens = @( | |
| @{ | |
| Width = [WindowAPI]::GetSystemMetrics([WindowAPI]::SM_CXSCREEN) | |
| Height = [WindowAPI]::GetSystemMetrics([WindowAPI]::SM_CYSCREEN) | |
| Left = 0 | |
| Top = 0 | |
| IsPrimary = $true | |
| DeviceName = "Primary" | |
| } | |
| ) | |
| } | |
| } | |
| return $screenInfo | |
| } | |
| function Get-OffScreenWindows { | |
| <# | |
| .SYNOPSIS | |
| Gets a list of all windows that are currently positioned off-screen. | |
| .DESCRIPTION | |
| Enumerates all visible windows and identifies those that are positioned outside | |
| the current visible desktop area. This includes windows that are completely | |
| off-screen or mostly off-screen (with only a small portion visible). | |
| .PARAMETER ProcessName | |
| Optional filter to only check windows from processes matching this name. | |
| Supports wildcards. Example: "chrome", "vivaldi", "notepad" | |
| .PARAMETER IncludeMinimized | |
| Include minimized windows in the search. By default, minimized windows are ignored. | |
| .PARAMETER Tolerance | |
| Number of pixels a window can be off-screen before being considered "off-screen". | |
| Default is 100 pixels to allow for partially visible windows. | |
| .EXAMPLE | |
| Get-OffScreenWindows | |
| Returns all off-screen windows. | |
| .EXAMPLE | |
| Get-OffScreenWindows -ProcessName "vivaldi" | |
| Returns only Vivaldi browser windows that are off-screen. | |
| .EXAMPLE | |
| Get-OffScreenWindows -Verbose -Tolerance 50 | |
| Returns off-screen windows with detailed information and custom tolerance. | |
| #> | |
| [CmdletBinding()] | |
| param( | |
| [string]$ProcessName = "", | |
| [switch]$IncludeMinimized, | |
| [int]$Tolerance = 100 | |
| ) | |
| $screenInfo = Get-ScreenInformation | |
| $primaryScreen = $screenInfo.Primary | |
| Write-Verbose "Primary screen: $($primaryScreen.Width)x$($primaryScreen.Height) at ($($primaryScreen.Left), $($primaryScreen.Top))" | |
| # Get target process IDs if filtering | |
| $targetProcessIds = @() | |
| if ($ProcessName) { | |
| $processes = Get-Process | Where-Object { $_.ProcessName -like "*$ProcessName*" } | |
| $targetProcessIds = $processes | Select-Object -ExpandProperty Id | |
| Write-Verbose "Found $($targetProcessIds.Count) processes matching '$ProcessName'" | |
| } | |
| $offScreenWindows = @() | |
| # Enumerate all windows | |
| $enumCallback = { | |
| param($hWnd, $lParam) | |
| try { | |
| $processId = 0 | |
| [WindowAPI]::GetWindowThreadProcessId($hWnd, [ref]$processId) | |
| # Filter by process if specified | |
| if ($ProcessName -and $targetProcessIds -notcontains $processId) { | |
| return $true | |
| } | |
| # Check if window is visible | |
| if (-not [WindowAPI]::IsWindowVisible($hWnd)) { | |
| return $true | |
| } | |
| # Check if window is minimized (skip unless explicitly requested) | |
| if (-not $IncludeMinimized -and [WindowAPI]::IsIconic($hWnd)) { | |
| return $true | |
| } | |
| # Get window rectangle | |
| $rect = New-Object RECT | |
| [WindowAPI]::GetWindowRect($hWnd, [ref]$rect) | |
| # Get window title | |
| $length = [WindowAPI]::GetWindowTextLength($hWnd) | |
| $title = "" | |
| if ($length -gt 0) { | |
| $sb = New-Object System.Text.StringBuilder($length + 1) | |
| [WindowAPI]::GetWindowText($hWnd, $sb, $sb.Capacity) | |
| $title = $sb.ToString() | |
| } | |
| # Calculate window dimensions | |
| $windowWidth = $rect.right - $rect.left | |
| $windowHeight = $rect.bottom - $rect.top | |
| # Skip very small windows (likely system windows) or windows without titles | |
| if ($windowWidth -lt 50 -or $windowHeight -lt 50 -or $title.Length -eq 0) { | |
| return $true | |
| } | |
| # Check if window is off-screen | |
| $isOffScreen = ( | |
| $rect.left -lt ($primaryScreen.Left - $Tolerance) -or | |
| $rect.top -lt ($primaryScreen.Top - $Tolerance) -or | |
| $rect.right -gt ($primaryScreen.Left + $primaryScreen.Width + $Tolerance) -or | |
| $rect.bottom -gt ($primaryScreen.Top + $primaryScreen.Height + $Tolerance) -or | |
| $rect.right -lt ($primaryScreen.Left + $Tolerance) -or | |
| $rect.bottom -lt ($primaryScreen.Top + $Tolerance) | |
| ) | |
| if ($isOffScreen) { | |
| # Get process information | |
| $process = Get-Process -Id $processId -ErrorAction SilentlyContinue | |
| $processName = if ($process) { $process.ProcessName } else { "Unknown" } | |
| $windowInfo = [PSCustomObject]@{ | |
| Handle = $hWnd | |
| ProcessId = $processId | |
| ProcessName = $processName | |
| Title = $title | |
| Left = $rect.left | |
| Top = $rect.top | |
| Right = $rect.right | |
| Bottom = $rect.bottom | |
| Width = $windowWidth | |
| Height = $windowHeight | |
| IsMinimized = [WindowAPI]::IsIconic($hWnd) | |
| OffScreenReason = @() | |
| } | |
| # Determine why it's considered off-screen | |
| if ($rect.left -lt ($primaryScreen.Left - $Tolerance)) { | |
| $windowInfo.OffScreenReason += "Left edge off-screen" | |
| } | |
| if ($rect.top -lt ($primaryScreen.Top - $Tolerance)) { | |
| $windowInfo.OffScreenReason += "Top edge off-screen" | |
| } | |
| if ($rect.right -gt ($primaryScreen.Left + $primaryScreen.Width + $Tolerance)) { | |
| $windowInfo.OffScreenReason += "Right edge off-screen" | |
| } | |
| if ($rect.bottom -gt ($primaryScreen.Top + $primaryScreen.Height + $Tolerance)) { | |
| $windowInfo.OffScreenReason += "Bottom edge off-screen" | |
| } | |
| if ($rect.right -lt ($primaryScreen.Left + $Tolerance)) { | |
| $windowInfo.OffScreenReason += "Completely left of screen" | |
| } | |
| if ($rect.bottom -lt ($primaryScreen.Top + $Tolerance)) { | |
| $windowInfo.OffScreenReason += "Completely above screen" | |
| } | |
| $offScreenWindows += $windowInfo | |
| } | |
| } | |
| catch { | |
| Write-Verbose "Error processing window: $($_.Exception.Message)" | |
| } | |
| return $true | |
| } | |
| # Execute the enumeration | |
| [WindowAPI]::EnumWindows($enumCallback, [IntPtr]::Zero) | Out-Null | |
| Write-Verbose "Found $($offScreenWindows.Count) off-screen windows" | |
| return $offScreenWindows | |
| } | |
| function Repair-OffScreenWindows { | |
| <# | |
| .SYNOPSIS | |
| Brings all off-screen windows back onto the current desktop. | |
| .DESCRIPTION | |
| This function finds all windows that are positioned outside the visible screen area | |
| and moves them back to a visible location. Useful when windows get stuck off-screen | |
| after disconnecting external monitors or changing display configurations. | |
| .PARAMETER ProcessName | |
| Optional. Filter windows by process name (e.g., 'vivaldi', 'chrome', 'notepad'). | |
| If not specified, all off-screen windows will be moved. | |
| .PARAMETER IncludeMinimized | |
| Include minimized windows in the recovery process. By default, minimized windows are ignored. | |
| .PARAMETER Tolerance | |
| Number of pixels a window can be off-screen before being considered "off-screen". | |
| Default is 100 pixels to allow for partially visible windows. | |
| .PARAMETER Position | |
| Where to position recovered windows. Options: 'Cascade', 'TopLeft', 'Center', 'TopRight' | |
| Default is 'Cascade' which positions windows in a cascading pattern. | |
| .PARAMETER RestoreMinimized | |
| If true, minimized off-screen windows will be restored (un-minimized) when moved. | |
| .PARAMETER BringToFront | |
| If true, recovered windows will be brought to the foreground. | |
| .EXAMPLE | |
| Repair-OffScreenWindows | |
| Moves all off-screen windows back to the visible desktop using cascade positioning. | |
| .EXAMPLE | |
| Repair-OffScreenWindows -ProcessName vivaldi -Verbose | |
| Moves only Vivaldi browser windows that are off-screen with detailed output. | |
| .EXAMPLE | |
| Repair-OffScreenWindows -Position Center -BringToFront | |
| Centers all off-screen windows and brings them to the front. | |
| .EXAMPLE | |
| Repair-OffScreenWindows -IncludeMinimized -RestoreMinimized | |
| Includes minimized windows and restores them when moving. | |
| #> | |
| [CmdletBinding()] | |
| param( | |
| [string]$ProcessName = "", | |
| [switch]$IncludeMinimized, | |
| [int]$Tolerance = 100, | |
| [ValidateSet('Cascade', 'TopLeft', 'Center', 'TopRight')] | |
| [string]$Position = 'Cascade', | |
| [switch]$RestoreMinimized, | |
| [switch]$BringToFront | |
| ) | |
| # Get off-screen windows | |
| $offScreenWindows = Get-OffScreenWindows -ProcessName $ProcessName -IncludeMinimized:$IncludeMinimized -Tolerance $Tolerance -Verbose:$VerbosePreference | |
| if ($offScreenWindows.Count -eq 0) { | |
| Write-Host "No off-screen windows found." -ForegroundColor Green | |
| return @() | |
| } | |
| Write-Host "Found $($offScreenWindows.Count) off-screen window$(if ($offScreenWindows.Count -ne 1) {'s'}):" -ForegroundColor Yellow | |
| $screenInfo = Get-ScreenInformation | |
| $primaryScreen = $screenInfo.Primary | |
| $movedWindows = @() | |
| $windowsMoved = 0 | |
| foreach ($window in $offScreenWindows) { | |
| try { | |
| Write-Verbose "Processing window: '$($window.Title)' (PID: $($window.ProcessId))" | |
| # Calculate new position based on positioning strategy | |
| switch ($Position) { | |
| 'TopLeft' { | |
| $newX = $primaryScreen.Left + 50 | |
| $newY = $primaryScreen.Top + 50 | |
| } | |
| 'Center' { | |
| $newX = $primaryScreen.Left + ($primaryScreen.Width - $window.Width) / 2 | |
| $newY = $primaryScreen.Top + ($primaryScreen.Height - $window.Height) / 2 | |
| } | |
| 'TopRight' { | |
| $newX = $primaryScreen.Left + $primaryScreen.Width - $window.Width - 50 | |
| $newY = $primaryScreen.Top + 50 | |
| } | |
| 'Cascade' { | |
| $newX = $primaryScreen.Left + 50 + ($windowsMoved * 30) | |
| $newY = $primaryScreen.Top + 50 + ($windowsMoved * 30) | |
| } | |
| } | |
| # Ensure window fits on screen | |
| $newX = [Math]::Max($primaryScreen.Left, [Math]::Min($newX, $primaryScreen.Left + $primaryScreen.Width - $window.Width)) | |
| $newY = [Math]::Max($primaryScreen.Top, [Math]::Min($newY, $primaryScreen.Top + $primaryScreen.Height - $window.Height)) | |
| # Additional bounds checking | |
| if ($newX + $window.Width -gt $primaryScreen.Left + $primaryScreen.Width) { | |
| $newX = $primaryScreen.Left + $primaryScreen.Width - $window.Width - 10 | |
| } | |
| if ($newY + $window.Height -gt $primaryScreen.Top + $primaryScreen.Height) { | |
| $newY = $primaryScreen.Top + $primaryScreen.Height - $window.Height - 10 | |
| } | |
| # Ensure coordinates are not negative | |
| $newX = [Math]::Max($primaryScreen.Left, $newX) | |
| $newY = [Math]::Max($primaryScreen.Top, $newY) | |
| Write-Verbose "Moving '$($window.Title)' from ($($window.Left), $($window.Top)) to ($newX, $newY)" | |
| # Restore minimized window if requested | |
| if ($window.IsMinimized -and $RestoreMinimized) { | |
| [WindowAPI]::ShowWindow($window.Handle, [WindowAPI]::SW_RESTORE) | Out-Null | |
| Write-Verbose "Restored minimized window" | |
| } | |
| # Move the window | |
| $success = [WindowAPI]::SetWindowPos( | |
| $window.Handle, | |
| [IntPtr]::Zero, | |
| [int]$newX, | |
| [int]$newY, | |
| 0, | |
| 0, | |
| [WindowAPI]::SWP_NOSIZE -bor [WindowAPI]::SWP_NOZORDER -bor [WindowAPI]::SWP_SHOWWINDOW | |
| ) | |
| if ($success) { | |
| $windowsMoved++ | |
| # Bring to front if requested | |
| if ($BringToFront) { | |
| [WindowAPI]::SetForegroundWindow($window.Handle) | Out-Null | |
| } | |
| $movedWindow = $window.PSObject.Copy() | |
| $movedWindow | Add-Member -NotePropertyName NewLeft -NotePropertyValue $newX | |
| $movedWindow | Add-Member -NotePropertyName NewTop -NotePropertyValue $newY | |
| $movedWindow | Add-Member -NotePropertyName MoveSuccessful -NotePropertyValue $true | |
| $movedWindows += $movedWindow | |
| Write-Host " ✓ Moved: $($window.Title)" -ForegroundColor Green | |
| if ($VerbosePreference -eq 'Continue') { | |
| Write-Host " Process: $($window.ProcessName) (PID: $($window.ProcessId))" -ForegroundColor Gray | |
| Write-Host " Reason: $($window.OffScreenReason -join ', ')" -ForegroundColor Gray | |
| Write-Host " Position: ($($window.Left), $($window.Top)) → ($newX, $newY)" -ForegroundColor Gray | |
| } | |
| } | |
| else { | |
| Write-Host " ✗ Failed to move: $($window.Title)" -ForegroundColor Red | |
| $failedWindow = $window.PSObject.Copy() | |
| $failedWindow | Add-Member -NotePropertyName MoveSuccessful -NotePropertyValue $false | |
| $failedWindow | Add-Member -NotePropertyName FailureReason -NotePropertyValue "SetWindowPos failed" | |
| $movedWindows += $failedWindow | |
| } | |
| } | |
| catch { | |
| Write-Host " ✗ Error moving window '$($window.Title)': $($_.Exception.Message)" -ForegroundColor Red | |
| $failedWindow = $window.PSObject.Copy() | |
| $failedWindow | Add-Member -NotePropertyName MoveSuccessful -NotePropertyValue $false | |
| $failedWindow | Add-Member -NotePropertyName FailureReason -NotePropertyValue $_.Exception.Message | |
| $movedWindows += $failedWindow | |
| } | |
| } | |
| # Summary | |
| $successCount = ($movedWindows | Where-Object { $_.MoveSuccessful }).Count | |
| $failCount = ($movedWindows | Where-Object { -not $_.MoveSuccessful }).Count | |
| Write-Host "" | |
| Write-Host "Recovery Summary:" -ForegroundColor Cyan | |
| Write-Host " Successfully moved: $successCount" -ForegroundColor Green | |
| Write-Host " Failed to move: $failCount" -ForegroundColor $(if ($failCount -gt 0) { 'Red' } else { 'Gray' }) | |
| Write-Host " Total processed: $($movedWindows.Count)" -ForegroundColor White | |
| return $movedWindows | |
| } | |
| function Show-ScreenInformation { | |
| <# | |
| .SYNOPSIS | |
| Displays information about the current screen configuration. | |
| .DESCRIPTION | |
| Shows details about the primary screen and all connected displays, | |
| including dimensions and positions. Useful for troubleshooting | |
| off-screen window issues. | |
| .EXAMPLE | |
| Show-ScreenInformation | |
| Displays current screen configuration. | |
| #> | |
| [CmdletBinding()] | |
| param() | |
| $screenInfo = Get-ScreenInformation | |
| Write-Host "Screen Configuration:" -ForegroundColor Cyan | |
| Write-Host "" | |
| Write-Host "Primary Screen:" -ForegroundColor Yellow | |
| Write-Host " Dimensions: $($screenInfo.Primary.Width) x $($screenInfo.Primary.Height)" -ForegroundColor White | |
| Write-Host " Position: ($($screenInfo.Primary.Left), $($screenInfo.Primary.Top))" -ForegroundColor White | |
| Write-Host "" | |
| if ($screenInfo.AllScreens.Count -gt 1) { | |
| Write-Host "All Screens:" -ForegroundColor Yellow | |
| for ($i = 0; $i -lt $screenInfo.AllScreens.Count; $i++) { | |
| $screen = $screenInfo.AllScreens[$i] | |
| $isPrimary = if ($screen.IsPrimary) { " (Primary)" } else { "" } | |
| Write-Host " Screen $($i + 1)$isPrimary : $($screen.Width) x $($screen.Height) at ($($screen.Left), $($screen.Top))" -ForegroundColor White | |
| if ($screen.DeviceName) { | |
| Write-Host " Device: $($screen.DeviceName)" -ForegroundColor Gray | |
| } | |
| } | |
| Write-Host "" | |
| } | |
| Write-Host "Virtual Desktop:" -ForegroundColor Yellow | |
| Write-Host " Total area: $($screenInfo.Virtual.Width) x $($screenInfo.Virtual.Height)" -ForegroundColor White | |
| Write-Host " Top-left: ($($screenInfo.Virtual.Left), $($screenInfo.Virtual.Top))" -ForegroundColor White | |
| } | |
| # Export module members | |
| Export-ModuleMember -Function @( | |
| 'Get-OffScreenWindows', | |
| 'Repair-OffScreenWindows', | |
| 'Show-ScreenInformation' | |
| ) | |
| # Create aliases for common usage patterns - avoid conflicts during reloading | |
| if (-not (Get-Alias 'Fix-Windows' -ErrorAction SilentlyContinue)) { | |
| New-Alias -Name 'Fix-Windows' -Value 'Repair-OffScreenWindows' -Description "Alias for Repair-OffScreenWindows" | |
| } | |
| if (-not (Get-Alias 'Bring-Windows' -ErrorAction SilentlyContinue)) { | |
| New-Alias -Name 'Bring-Windows' -Value 'Repair-OffScreenWindows' -Description "Alias for Repair-OffScreenWindows" | |
| } | |
| if (-not (Get-Alias 'Recover-Windows' -ErrorAction SilentlyContinue)) { | |
| New-Alias -Name 'Recover-Windows' -Value 'Repair-OffScreenWindows' -Description "Alias for Repair-OffScreenWindows" | |
| } | |
| if (-not (Get-Alias 'Find-OffScreenWindows' -ErrorAction SilentlyContinue)) { | |
| New-Alias -Name 'Find-OffScreenWindows' -Value 'Get-OffScreenWindows' -Description "Alias for Get-OffScreenWindows" | |
| } | |
| if (-not (Get-Alias 'Screen-Info' -ErrorAction SilentlyContinue)) { | |
| New-Alias -Name 'Screen-Info' -Value 'Show-ScreenInformation' -Description "Alias for Show-ScreenInformation" | |
| } | |
| Export-ModuleMember -Alias @( | |
| 'Fix-Windows', | |
| 'Bring-Windows', | |
| 'Recover-Windows', | |
| 'Find-OffScreenWindows', | |
| 'Screen-Info' | |
| ) | |
| # Module initialization message | |
| Write-Host "Off-Screen Window Recovery Module loaded!" -ForegroundColor Green | |
| Write-Host "Available commands:" -ForegroundColor Yellow | |
| Write-Host " • Repair-OffScreenWindows (Fix-Windows)" -ForegroundColor White | |
| Write-Host " • Get-OffScreenWindows (Find-OffScreenWindows)" -ForegroundColor White | |
| Write-Host " • Show-ScreenInformation (Screen-Info)" -ForegroundColor White | |
| Write-Host "" | |
| Write-Host "Quick start: Run 'Fix-Windows' to recover all off-screen windows" -ForegroundColor Cyan |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment