最小化窗口通常可以通过激活窗口(将其置于前台)然后使用SendKeys() 发送 Alt+Space 来完成,然后发送任何字母区域设置为“最小化”(英文 Windows 中的 N)加了下划线。 Here's one 可能有几十个使用 VBScript 的示例。
在我看来,这个序列被过度使用、不优雅和无聊——而且它不适用于某些窗口(例如 cmd 控制台)。可以在不将其置于前台且不模拟按键的情况下最小化窗口。只需从 user32.dll 导入一个函数。只要我们遇到了这个麻烦,我们还不如导入第二个函数来检测当前窗口状态,这样我们就可以切换最小化/恢复。
我们可以像这样使用 PowerShell 导入函数。保存这个带有 .bat 扩展名的 Batch / PowerShell 混合脚本并运行它。
<# : minimize.bat
:: toggles minimized state of a window by its filename
:: minimize.bat /? for usage
:: https://stackoverflow.com/a/34834953/1683264
@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);
'@ -namespace System
$hwnd = @(Get-Process $env:prog)[0].MainWindowHandle
$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
}
现在,如果您的程序最小化到系统托盘,之前的脚本可以很好地最小化,但在最小化时将无法找到窗口句柄。尝试恢复时会失败。在这种情况下找到 HWND 是很棘手的。如果知道窗口标题,可以使用 user32.dll FindWindow() 或 FindWindowEx() 函数找到 HWND。
我在使用 WMI 或内置 PowerShell 命令来查找最小化到托盘的窗口标题时运气不佳。 get-process 和 gwmi win32_process 和 [diagnostics.process]::getProcessByName() 都没有成功。然而,我确实发现tasklist /v /fo list 的最后一行将显示窗口标题。这足以调用 FindWindow() 并获取 HWND。
这可能比它需要的更复杂,但也可能不会。我只知道我找到了 1000 种失败的方法,但只有一种方法可以成功。 Thanks to JPBlanc 帮助我弄清楚如何将空参数传递给 FindWindow() 和 FindWindowEx()。
<# : 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 FindWindow(IntPtr lpClassName, string lpWindowName);
[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]::FindWindow($zero, $title)
if ($hwnd -eq 0) {
$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
}