5

In Windows if I want to list all instances (and window titles) of a given application from the command line I run this command:

tasklist /fi "IMAGENAME eq notepad.exe" /v

However I can't do the same thing for applications such as LibreOffice. For example no matter how many different Writer windows I may have open, there always is only one soffice.bin and one soffice.exe process. Using the tasklist command I can only see one window title associated with soffice.bin process.

Same thing happens with Microsoft Word (only one winword.exe process exists and is associated with only one window title).

Is there any way I can list all the window titles of such applications through the command line?

3
  • 2
    cmdow shows some more entries.
    – LotPings
    Commented Jun 3, 2018 at 23:53
  • 1
    Does this help: superuser.com/questions/378790/… ? See the answer with no AutoHotkey. Commented Jun 4, 2018 at 2:55
  • 1
    Thanks, both cmdow and AutoHotkey give me the window titles. I was hoping for a native solution without third party software though but I don't think it is possible.
    – AndroidX
    Commented Jun 4, 2018 at 8:05

1 Answer 1

2

You can use the following PowerShell script:

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

I wrote a program that allows filtering this list and brings the selected window to the front: activatewindow

2
  • It works (not in PowerShell 2.0 though).
    – AndroidX
    Commented Sep 13, 2021 at 13:20
  • If you'd like to get the accompanying process names and process id:s as well, have a look at this answer at stackoverflow
    – Dennis
    Commented May 13 at 19:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .