The comments and examples explain how to use it.
Code: Select all
@echo off &setlocal
:: define the show_hide_window macro variable
call :init_show_hide_window
:: create a PowerShell process with iconic window
:: pause to give you the opportunity to observe the icon on the task bar
:: maximize the window
start /min powershell.exe
pause
%show_hide_window% MAXIMIZE "$_.WINDOWTITLE -eq 'Windows PowerShell'"
echo %errorlevel%
:: create two Notepad processes with iconic window
:: pause to give you the opportunity to observe the icons on the task bar
:: maximize the first window and pause
:: hide the second window and pause (observe the disappeared icon on the task bar)
:: bring the second window to front in normal style
:: after a second minimize it to the task bar and pause
>"%temp%\test.txt" echo pick me first
start /min notepad.exe "%temp%\test.txt"
>"%temp%\another test.txt" echo leave me alone for a while
start /min notepad.exe "%temp%\another test.txt"
pause
del "%temp%\test.txt"
del "%temp%\another test.txt"
%show_hide_window% MAXIMIZE "$_.IMAGENAME -eq 'notepad.exe' -and $_.WINDOWTITLE -like 'test.txt - *'"
echo %errorlevel%
pause
%show_hide_window% HIDE "$_.IMAGENAME -eq 'notepad.exe' -and $_.WINDOWTITLE -like 'another test.txt - *'"
echo %errorlevel%
pause
%show_hide_window% SHOWNORMAL "$_.IMAGENAME -eq 'notepad.exe' -and $_.WINDOWTITLE -like 'another test.txt - *'"
echo %errorlevel%
timeout 1
%show_hide_window% MINIMIZE "$_.IMAGENAME -eq 'notepad.exe' -and $_.WINDOWTITLE -like 'another test.txt - *'"
echo %errorlevel%
pause
goto :eof
:init_show_hide_window
:: - BRIEF -
:: Hide, minimize, or bring a window into the foreground and activate it. The window appearance
:: is defined by an ID. Selection takes place by custom filters. If the filter matches more
:: than one window then the first found window will be selected.
:: - SYNTAX -
:: %show_hide_window% showcmd "filter"
:: showcmd Command for the new window appearance. Valid arguments:
:: HIDE
:: MAXIMIZE
:: MINIMIZE
:: RESTORE
:: SHOWDEFAULT
:: SHOWNORMAL
:: filter Conditional expression using at least one of these properties:
:: $_.PID
:: $_.IMAGENAME
:: $_.WINDOWTITLE
:: Image names and window titles have to be enclosed into single quotes.
:: Conditions are following the syntax of PowerShell comparisons:
:: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_comparison_operators
:: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_logical_operators
:: - EXAMPLES -
:: Minimize the window with title "Windows PowerShell":
:: %show_hide_window% MINIMIZE "$_.WINDOWTITLE -eq 'Windows PowerShell'"
:: Hide the Notepad window whose title contains "foobar.txt":
:: %show_hide_window% HIDE "$_.IMAGENAME -eq 'notepad.exe' -and $_.WINDOWTITLE -like '*foobar.txt*'"
:: Maximize the main window of the process with process ID 1234:
:: %show_hide_window% MAXIMIZE "$_.PID -eq 1234"
setlocal DisableDelayedExpansion
set show_hide_window=for %%i in (1 2) do if %%i==2 (^
%=% for /f "tokens=1,2*" %%j in ("? ^^!arg^^!") do powershell.exe -nop -ep Bypass -c ^"try{Add-Type '^
%=% using System;using System.Text;using System.Collections.Generic;using System.Runtime.InteropServices;^
%=% public class Data{public IntPtr HWND;public int PID;public string IMAGENAME;public string WINDOWTITLE;}^
%=% public class Wnd{^
%=====% private delegate int CbPtr(IntPtr hWnd,IntPtr lPrm);^
%=====% private static List^^^^^^^<Data^^^^^^^> dataList=new List^^^^^^^<Data^^^^^^^>();^
%=====% [DllImport(\"user32.dll\")] static extern int EnumWindows(CbPtr func,IntPtr lPrm);^
%=====% [DllImport(\"user32.dll\")] static extern IntPtr GetWindow(IntPtr hWnd,int cmd);^
%=====% [DllImport(\"user32.dll\")] static extern int GetWindowText(IntPtr hWnd,StringBuilder str,int max);^
%=====% [DllImport(\"user32.dll\")] static extern int GetWindowThreadProcessId(IntPtr hWnd,ref int pid);^
%=====% [DllImport(\"kernel32.dll\")] static extern IntPtr OpenProcess(int access,int inherit,int pid);^
%=====% [DllImport(\"kernel32.dll\")] static extern int QueryFullProcessImageName(IntPtr hProc,int flags,StringBuilder exeName,ref int size);^
%=====% [DllImport(\"kernel32.dll\")] static extern int CloseHandle(IntPtr hObj);^
%=====% [DllImport(\"user32.dll\")] public static extern int ShowWindow(IntPtr hWnd,int show);^
%=====% [DllImport(\"user32.dll\")] public static extern int SetForegroundWindow(IntPtr hWnd);^
%=====% private static int CbProc(IntPtr hWnd,IntPtr lPrm){^
%=========% if (GetWindow(hWnd,4)==IntPtr.Zero){^
%=============% int pid=0,size=512;^
%=============% StringBuilder exe=new StringBuilder(size),title=new StringBuilder(size);^
%=============% int len=GetWindowText(hWnd,title,size);^
%=============% GetWindowThreadProcessId(hWnd,ref pid);^
%=============% IntPtr hProc=OpenProcess(4096,0,pid);^
%=============% QueryFullProcessImageName(hProc,0,exe,ref size);^
%=============% CloseHandle(hProc);^
%=============% if (len^^^^^^^>0^^^^^^^&^^^^^^^&size^^^^^^^>0)^
%=================% dataList.Add(new Data{HWND=hWnd,PID=pid,IMAGENAME=System.IO.Path.GetFileName(exe.ToString()),WINDOWTITLE=title.ToString()});^
%=========% }^
%=========% return 1;^
%=====% }^
%=====% public static List^^^^^^^<Data^^^^^^^> GetData(){^
%=========% EnumWindows(CbProc,IntPtr.Zero);^
%=========% return dataList;^
%=====% }^
%=% }';^
%=% $show=('HIDE','SHOWNORMAL','','MAXIMIZE','','','MINIMIZE','','','RESTORE','SHOWDEFAULT').IndexOf(\"%%~k\".ToUpper());^
%=% if(-1,2 -contains $show){exit 1;}^
%=% [Wnd]::GetData()^^^^^^^|?{%%~l;}^^^^^^^|%%{^
%=====% $e=[int]([Wnd]::ShowWindow($_.HWND,$show) -eq 0);^
%=====% if(0,6 -contains $show){exit $e;}^
%=====% exit [int]([Wnd]::SetForegroundWindow($_.HWND) -eq 0);^
%=% }}catch{exit 1;}exit 1;^"^&endlocal) else setlocal EnableDelayedExpansion^&set arg=
endlocal &set "show_hide_window=%show_hide_window%"
if !!# neq # set "show_hide_window=%show_hide_window:^^!=!%"
exit /b
- It's all about windows. Enumerating the top-level windows rather than the processes (that may not even have a window) is much more logical.
- However, the main reason is that the .MainWindowHandle property is null for hidden windows. Thus, unhiding windows wouldn't have been supported using Get-Process.
Steffen