通过命令行查找应用程序的所有窗口标题

通过命令行查找应用程序的所有窗口标题

在 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

我编写了一个程序,可以过滤此列表并将选定的窗口置于最前面:激活窗口

相关内容