-
-
Save lalibi/3762289efc5805f8cfcf to your computer and use it in GitHub Desktop.
Hide, Show, Minimize, Maximize, etc window from Powershell.
This file contains 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
function Set-WindowState { | |
<# | |
.SYNOPSIS | |
Set the state of a window. | |
.DESCRIPTION | |
Set the state of a window using the `ShowWindowAsync` function from `user32.dll`. | |
.PARAMETER InputObject | |
The process object(s) to set the state of. Can be piped from `Get-Process`. | |
.PARAMETER State | |
The state to set the window to. Default is 'SHOW'. | |
.PARAMETER SuppressErrors | |
Suppress errors when the main window handle is '0'. | |
.PARAMETER SetForegroundWindow | |
Set the window to the foreground | |
.PARAMETER ThresholdHours | |
The number of hours to keep the window handle in memory. Default is 24. | |
.EXAMPLE | |
Get-Process notepad | Set-WindowState -State HIDE -SuppressErrors | |
.EXAMPLE | |
Get-Process notepad | Set-WindowState -State SHOW -SuppressErrors | |
.LINK | |
https://gist.github.com/lalibi/3762289efc5805f8cfcf | |
.NOTES | |
Original idea from https://gist.github.com/Nora-Ballard/11240204 | |
#> | |
[CmdletBinding(DefaultParameterSetName = 'InputObject')] | |
param( | |
[Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] | |
[Object[]] $InputObject, | |
[Parameter(Position = 1)] | |
[ValidateSet( | |
'FORCEMINIMIZE', 'HIDE', 'MAXIMIZE', 'MINIMIZE', 'RESTORE', | |
'SHOW', 'SHOWDEFAULT', 'SHOWMAXIMIZED', 'SHOWMINIMIZED', | |
'SHOWMINNOACTIVE', 'SHOWNA', 'SHOWNOACTIVATE', 'SHOWNORMAL' | |
)] | |
[string] $State = 'SHOW', | |
[switch] $SuppressErrors = $false, | |
[switch] $SetForegroundWindow = $false, | |
[int] $ThresholdHours = 24 | |
) | |
Begin { | |
$WindowStates = @{ | |
'FORCEMINIMIZE' = 11 | |
'HIDE' = 0 | |
'MAXIMIZE' = 3 | |
'MINIMIZE' = 6 | |
'RESTORE' = 9 | |
'SHOW' = 5 | |
'SHOWDEFAULT' = 10 | |
'SHOWMAXIMIZED' = 3 | |
'SHOWMINIMIZED' = 2 | |
'SHOWMINNOACTIVE' = 7 | |
'SHOWNA' = 8 | |
'SHOWNOACTIVATE' = 4 | |
'SHOWNORMAL' = 1 | |
} | |
$Win32ShowWindowAsync = Add-Type -MemberDefinition @' | |
[DllImport("user32.dll")] | |
public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow); | |
[DllImport("user32.dll", SetLastError = true)] | |
public static extern bool SetForegroundWindow(IntPtr hWnd); | |
'@ -Name "Win32ShowWindowAsync" -Namespace Win32Functions -PassThru | |
$handlesFilePath = "$env:APPDATA\WindowHandles.json" | |
$global:MainWindowHandles = @{} | |
if (Test-Path $handlesFilePath) { | |
$json = Get-Content $handlesFilePath -Raw | |
$data = $json | ConvertFrom-Json | |
$currentTime = Get-Date | |
foreach ($key in $data.PSObject.Properties.Name) { | |
$handleData = $data.$key | |
if ($handleData -and $handleData.Timestamp) { | |
try { | |
$timestamp = [datetime] $handleData.Timestamp | |
if ($currentTime - $timestamp -lt (New-TimeSpan -Hours $ThresholdHours)) { | |
$global:MainWindowHandles[[int] $key] = $handleData | |
} | |
} catch { | |
Write-Verbose "Skipping invalid timestamp for handle $key" | |
} | |
} else { | |
Write-Verbose "Skipping entry for handle $key due to missing data" | |
} | |
} | |
} | |
} | |
Process { | |
foreach ($process in $InputObject) { | |
$handle = $process.MainWindowHandle | |
if ($handle -eq 0 -and $global:MainWindowHandles.ContainsKey($process.Id)) { | |
$handle = [int] $global:MainWindowHandles[$process.Id].Handle | |
} | |
if ($handle -eq 0) { | |
if (-not $SuppressErrors) { | |
Write-Error "Main Window handle is '0'" | |
} else { | |
Write-Verbose ("Skipping '{0}' with id '{1}', because Main Window handle is '0'" -f $process.ProcessName, $process.Id) | |
} | |
continue | |
} | |
Write-Verbose ("Processing '{0}' with id '{1}' and handle '{2}'" -f $process.ProcessName, $process.Id, $handle) | |
$global:MainWindowHandles[$process.Id] = @{ | |
Handle = $handle.ToString() | |
Timestamp = (Get-Date).ToString("o") | |
} | |
$Win32ShowWindowAsync::ShowWindowAsync($handle, $WindowStates[$State]) | Out-Null | |
if ($SetForegroundWindow) { | |
$Win32ShowWindowAsync::SetForegroundWindow($handle) | Out-Null | |
} | |
Write-Verbose ("» Set Window State '{1}' on '{0}'" -f $handle, $State) | |
} | |
} | |
End { | |
$data = [ordered] @{} | |
foreach ($key in $global:MainWindowHandles.Keys) { | |
if ($global:MainWindowHandles[$key].Handle -ne 0) { | |
$data["$key"] = $global:MainWindowHandles[$key] | |
} | |
} | |
$json = $data | ConvertTo-Json | |
Set-Content -Path $handlesFilePath -Value $json | |
} | |
} |
Wow, two years later, you still added a feature. That's awesome!
And I just realized I didn't respond, sorry about that lol.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
.json
now includes a timestamp for each entry and invalidates them, if a threshold is reached (default is 24 hours).