在 Windows 中,如果我想从命令行列出给定应用程序的所有实例(和窗口标题),我会运行以下命令:
tasklist /fi "IMAGENAME eq notepad.exe" /v
但是我无法对 LibreOffice 等应用程序执行相同的操作。例如,无论我打开了多少个不同的 Writer 窗口,始终只有一个soffice.bin
和一个soffice.exe
进程。使用该tasklist
命令,我只能看到一个与soffice.bin
进程关联的窗口标题。
Microsoft Word 也发生了同样的事情(只winword.exe
存在一个进程并且只与一个窗口标题相关联)。
有什么方法可以通过命令行列出此类应用程序的所有窗口标题?
答案1
您可以使用以下 PowerShell 脚本:
Add-Type @"
using System;
using System.Runtime.InteropServices;
using System.Text;
public class Win32 {
public delegate void ThreadDelegate(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")]
public static extern bool EnumThreadWindows(int dwThreadId,
ThreadDelegate lpfn, IntPtr lParam);
[DllImport("user32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern int GetWindowText(IntPtr hwnd,
StringBuilder lpString, int cch);
[DllImport("user32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern Int32 GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern bool IsIconic(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern bool IsWindowVisible(IntPtr hWnd);
public static string GetTitle(IntPtr hWnd) {
var len = GetWindowTextLength(hWnd);
StringBuilder title = new StringBuilder(len + 1);
GetWindowText(hWnd, title, title.Capacity);
return title.ToString();
}
}
"@
$windows = New-Object System.Collections.ArrayList
Get-Process | Where { $_.MainWindowTitle } | foreach {
$_.Threads.ForEach({
[void][Win32]::EnumThreadWindows($_.Id, {
param($hwnd, $lparam)
if ([Win32]::IsIconic($hwnd) -or [Win32]::IsWindowVisible($hwnd)) {
$windows.Add([Win32]::GetTitle($hwnd))
}}, 0)
})}
Write-Output $windows
我编写了一个程序,可以过滤此列表并将选定的窗口置于最前面:激活窗口