Skip to content

Instantly share code, notes, and snippets.

@Nora-Ballard
Last active September 17, 2024 03:03
Show Gist options
  • Save Nora-Ballard/11240204 to your computer and use it in GitHub Desktop.
Save Nora-Ballard/11240204 to your computer and use it in GitHub Desktop.
Hide, Show, Minimize, Maximize, etc window from Powershell.
function Set-WindowState {
param(
[Parameter()]
[ValidateSet('FORCEMINIMIZE', 'HIDE', 'MAXIMIZE', 'MINIMIZE', 'RESTORE',
'SHOW', 'SHOWDEFAULT', 'SHOWMAXIMIZED', 'SHOWMINIMIZED',
'SHOWMINNOACTIVE', 'SHOWNA', 'SHOWNOACTIVATE', 'SHOWNORMAL')]
[Alias('Style')]
[String] $State = 'SHOW',
[Parameter(ValueFromPipelineByPropertyname='True')]
[System.IntPtr] $MainWindowHandle = (Get-Process –id $pid).MainWindowHandle,
[Parameter()]
[switch] $PassThru
)
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);
“@ -name Win32ShowWindowAsync -namespace Win32Functions –passThru
}
PROCESS
{
$Win32ShowWindowAsync::ShowWindowAsync($MainWindowHandle, $WindowStates[$State]) | Out-Null
Write-Verbose ("Set Window State on '{0}' to '{1}' " -f $MainWindowHandle, $State)
if ($PassThru)
{
Write-Output $MainWindowHandle
}
}
END
{
}
}
Set-Alias -Name 'Set-WindowStyle' -Value 'Set-WindowState'
@OneSpecialPeg
Copy link

Rename the $State parameter to $Style to get this to work.

@Paluan
Copy link

Paluan commented Dec 16, 2014

thanks for this amazing script, just one thing to add
" “@ -name “Win32ShowWindowAsync” -namespace Win32Functions –passThru"
my powershell ask to remove spaces at beginig of this line

@flamingtoast13
Copy link

Perhaps this is outdated, but anyway, this script works really well and it would be cool if it accepted pipeline input

@lalibi
Copy link

lalibi commented Oct 27, 2015

Check my fork, I added pipeline support

@ed1chandler
Copy link

Very useful, but isn't this really setting the window's "state", not its "style"?
State - https://msdn.microsoft.com/en-us/library/windows/desktop/ms633548(v=vs.85).aspx
Style - https://msdn.microsoft.com/en-us/library/windows/desktop/ms632600(v=vs.85).aspx
Any ideas on how the actual "style" can be set?
Thanks.

@nspb001
Copy link

nspb001 commented Jan 8, 2018

Any idea how to minimize/hide a window that doesn't have a MainWindowHandle property? For example, starting printui.exe you will receive a MainWindowHandle=0. The window doesn't have buttons to minimize/maximize either. However, using win+d to minimize the desktop, minimizes the printui.exe process as well.

@Nora-Ballard
Copy link
Author

Thank you everyone for the feedback. I have made some updates to address everyone's feedback. I hope you find it useful.

@ed1chandler is correct that state is probably more accurate, I wrote this originally for hiding the PS console and named it off of the parameter on there (-WindowsStyle) which sets these properties. I have updated it to reflect that, and added aliases for 'style' to keep compatibility, but you can easily disable those if you need.

I fixed the bug @Paluan reported, that was my typo when I was trying to clean up the formatting.

I have updated the MainWindowHandle parameter to accept pipeline input by property name, so it will accept a process object piped into it now.

I have update the script to output the window handle object if the -PassThru parameter is provided.

@nspb001 I'm not sure. Perhaps starting it with Start-Process or System.Diagnostics.Process would have it on that process object, or perhaps it is a permissions issue with it running elevated?

@dazlab
Copy link

dazlab commented Oct 20, 2020

Is there any way to get this to open up in fullscreen?

@Nora-Ballard
Copy link
Author

Is there any way to get this to open up in fullscreen?

I don’t think so, at least not with the API call that is being used currently. We are just calling an existing Windows API function and giving it values that it accepts.

@Offertorium
Copy link

Hi, what is the best way to minimize a window if the process name has a period. The process looks like this name_1.0 But the script runs very well otherwise. Thank you very much for that

@muraii
Copy link

muraii commented Oct 11, 2022

I am going to ask the dumb question: how should this be invoked? I've tried

> Get-Process *PowerShell* | Set-WindowState -State "SHOW"

and nothing happens. I've got three or four hidden PowerShell windows, but no dice. I then pulled a specific PID (say, 3372) and passed it like

> Get-Process -id 3372 | Set-WindowState -State "SHOW"

and still didn't see any response. I know the script's doing something because if I pass -PassThru I get a value of MainWindowHandle. I am tempted to think I'm getting the MainWindowHandle value for the window in which I'm invoking it. But I just don't grok PowerShell script parameters I guess.

Is it possibly that MainWindowHandle is set depending on the way in which the shell was invoked? Like, I've got a non-zero integer value for one of my PowerShell processes, but all the others have a value of zero.

@surfaceowl
Copy link

hey Nora - really great work here!

I ran into a few issues getting the gist to run on my Win 11 setup. To make it easier than finding minor changes in this thread, I posted a new repo here for your consideration. https://github.com/surfaceowl/Set-WindowState.ps1

There are three files there to help see the changes in steps-

  1. Set-WindowState.ps1 -- directly from Nora's gist, for reference / diffs
  2. Set-WindowState-v2-basic-fixes.ps1 -- corrects quote and dash chars that cause powershell errors on my install
  3. Set-WindowState-v3-style-suggestions.ps1 -- building on v2, some minor order/style changes

Using Set-WindowState-v2-basic-fixes.ps1 as an example, once this function is referenced in your powershell profile you can run from your terminal anywhere with something like: Get-Process *Evernote* | Set-WindowState -State "MINIMIZE" ...that just finds all the instances of a process and then minimizes

This is super helpful for managing annoying recurring tasks in Task Scheduler you can put this in a script file (e.g. paste cmd above into a file named minimize_evernote.ps1 and setup a new task in Task Scheduler. The cmd below will run the script silently, importantly avoiding a quick pop-up or flash of a powershell window that some may find annoying or worrisome (especially if run at startup). Configure the task with:
Program/script: cmd
Add arguments:

/c start /min "" Powershell -WindowStyle Hidden -ExecutionPolicy Bypass -File "C:\Users\chris\dev\powershell_scripts\minimize_evernote.ps1"

(of course, change the line above to match whatever path and filename used on your system)

@antatec
Copy link

antatec commented May 22, 2024

Hi! Thank you very much Nora-Ballard for this code.

I've found once window has MainWindowHandle = 0, you cannot handle it or bring it back. In example: "SystemSettings" process startis with MainWindowHandle = 0 and does not respond to MINIMIZE. Same, if you send a HIDE handle to a process, you cannot get it back even when the process is there.

Haven't found a way to sort this. Thanks.

@lalibi
Copy link

lalibi commented May 24, 2024

Hi! Thank you very much Nora-Ballard for this code.

I've found once window has MainWindowHandle = 0, you cannot handle it or bring it back. In example: "SystemSettings" process startis with MainWindowHandle = 0 and does not respond to MINIMIZE. Same, if you send a HIDE handle to a process, you cannot get it back even when the process is there.

Haven't found a way to sort this. Thanks.

You can check my fork. I store the MainWindowHandles in a .json file in "$env:APPDATA\WindowHandles.json" and restore them every time the script is run. These entries are cleared after a threshold (default = 24h).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment