7

I want to list all windows of a process, say Word. This only gives me main window:

Get-Process winword |where {$_.mainWindowTItle} |format-table id,name,mainwindowtitle –AutoSize

I want to also list Document1 here.

Id Name MainWindowTitle


1616 WINWORD Document2 - Microsoft Word

is there any way to access windows other than main one?

  • 2
    You could use the [EnumWindows](http://stackoverflow.com/questions/820909/get-applications-window-handles) function. However, that's Win32 code rather than .NET code, so it may not be the most straightforward approach. Keep in mind that [many applications use hidden windows](http://stackoverflow.com/questions/2970184/issue-with-enumwindows). I don't know of any PowerShell or .NET native approach. – Bacon Bits Sep 10 '14 at 17:34

1 Answers1

9

Thanks to Bacon Bits suggestion I managed to find a solution, but if you have any less cumbersome than this, please share:

<#
 .Synopsis
 Enumerieren der vorhandenen Fenster
#>

$TypeDef = @"

using System;
using System.Text;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace Api
{

 public class WinStruct
 {
   public string WinTitle {get; set; }
   public int WinHwnd { get; set; }
 }

 public class ApiDef
 {
   private delegate bool CallBackPtr(int hwnd, int lParam);
   private static CallBackPtr callBackPtr = Callback;
   private static List<WinStruct> _WinStructList = new List<WinStruct>();

   [DllImport("User32.dll")]
   [return: MarshalAs(UnmanagedType.Bool)]
   private static extern bool EnumWindows(CallBackPtr lpEnumFunc, IntPtr lParam);

   [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
   static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);

   private static bool Callback(int hWnd, int lparam)
   {
       StringBuilder sb = new StringBuilder(256);
       int res = GetWindowText((IntPtr)hWnd, sb, 256);
      _WinStructList.Add(new WinStruct { WinHwnd = hWnd, WinTitle = sb.ToString() });
       return true;
   }   

   public static List<WinStruct> GetWindows()
   {
      _WinStructList = new List<WinStruct>();
      EnumWindows(callBackPtr, IntPtr.Zero);
      return _WinStructList;
   }

 }
}
"@

Add-Type -TypeDefinition $TypeDef -Language CSharpVersion3

[Api.Apidef]::GetWindows() | Where-Object { $_.WinTitle -like "*Word" } | Sort-Object -Property WinTitle | Select-Object WinTitle,@{Name="Handle"; Expression={"{0:X0}" -f $_.WinHwnd}}
  • It not cumbersome and taught me how to integrate C# into PowerShell and making it a kind of polyglot. Thanks for that! The core is very similar to a Delphi program not just finding a Window, but acting on it at https://gist.github.com/jpluimers/77b24e5bce6970d4924e293d2e414612 so I will convert that to a PowerShell/C# combo. – Jeroen Wiert Pluimers Sep 14 '22 at 15:10
  • Seems the original source is mentioned at https://superuser.com/a/677035/14061: it is the (now defunct and not available in the Wayback Machine) http://powershell-knowhow.de/powershell/?p=321 – Jeroen Wiert Pluimers Sep 17 '22 at 09:05