I wrote this script for a user who wants to toggle the minimized state of a window that minimizes to the tray. The user required a .bat script, so I wrote a bat + PowerShell hybrid script in order to import functions from user32.dll.
<# : minimize.bat
:: toggles minimized state of a window by its filename
:: minimize.bat /? for usage
@echo off & setlocal
if "%~1"=="" goto usage
set "prog=%~n1"
tasklist | findstr /i "\<%prog%\>" >NUL || goto usage
set /P "=Toggling the minimized state of %prog%... " <NUL
powershell -noprofile -noninteractive "iex ((gc \"%~f0\") -join \"`n\")"
goto :EOF
:usage
echo syntax: %~nx0 progname[.exe]
echo;
echo If the program is visible, minimize it. If minimized, restore it.
goto :EOF
End batch / begin PowerShell hybrid chimera #>
Add-Type user32_dll @'
[DllImport("user32.dll")]
public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter,
IntPtr lclassName, string windowTitle);
'@ -namespace System
$hwnd = (ps $env:prog)[0].MainWindowHandle
if ($hwnd -eq 0) {
tasklist /v /fi "imagename eq $env:prog*" /fo list | %{
$title = $_ -replace '^[^:]+:\s+'
}
$zero = [IntPtr]::Zero
$hwnd = [user32_dll]::FindWindowEx($zero, $zero, $zero, $title)
}
$state = [user32_dll]::GetWindowLong($hwnd, -16)
# mask of 0x20000000 = minimized; 2 = minimize; 4 = restore
if ($state -band 0x20000000) { $action = 4 } else { $action = 2 }
if ([user32_dll]::ShowWindowAsync($hwnd, $action)) {
write-host "Success" -f green
} else {
write-host "Fail" -f red
}
Questions:
Neither the
get-process
cmdlet norgwmi win32_process
nor[diagnostics.process]::getProcessByName()
would show me either the window title or the HWND of a window that's minimized to the tray (uTorrent, for example). Is there an API method I missed, or istasklist.exe
the correct hack here?Is there any situation where
FindWindowEx()
would not be able to find a window that could be found withFindWindow()
? Should I import and useFindWindow()
as well?
Suggested improvements and other comments (not including "Why not just write the whole thing in PowerShell?") are welcome, of course!