First you should check WASP and see if it is suitable for your needs: http://wasp.codeplex.com/
Secondly, I changed the code found here http://social.technet.microsoft.com/Forums/windowsserver/en-US/c3cd3982-ffc5-4c17-98fc-a09c555e121c/get-all-child-window-titles? forum = winserverpowershell
to create a function that will take MainWindowHandle as input, and provide you with an object with the identifiers of the child descriptors (it will also display all the window names, if any).
I hope one of these methods gives you what you need :)
function Get-ChildWindow{ [CmdletBinding()] param ( [Parameter(ValueFromPipeline = $true, ValueFromPipelinebyPropertyName = $true)] [ValidateNotNullorEmpty()] [System.IntPtr]$MainWindowHandle ) BEGIN{ function Get-WindowName($hwnd) { $len = [apifuncs]::GetWindowTextLength($hwnd) if($len -gt 0){ $sb = New-Object text.stringbuilder -ArgumentList ($len + 1) $rtnlen = [apifuncs]::GetWindowText($hwnd,$sb,$sb.Capacity) $sb.tostring() } } if (("APIFuncs" -as [type]) -eq $null){ Add-Type @" using System; using System.Runtime.InteropServices; using System.Collections.Generic; using System.Text; public class APIFuncs { [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern int GetWindowText(IntPtr hwnd,StringBuilder lpString, int cch); [DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)] public static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)] public static extern Int32 GetWindowThreadProcessId(IntPtr hWnd,out Int32 lpdwProcessId); [DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)] public static extern Int32 GetWindowTextLength(IntPtr hWnd); [DllImport("user32")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i); public static List<IntPtr> GetChildWindows(IntPtr parent) { List<IntPtr> result = new List<IntPtr>(); GCHandle listHandle = GCHandle.Alloc(result); try { EnumWindowProc childProc = new EnumWindowProc(EnumWindow); EnumChildWindows(parent, childProc,GCHandle.ToIntPtr(listHandle)); } finally { if (listHandle.IsAllocated) listHandle.Free(); } return result; } private static bool EnumWindow(IntPtr handle, IntPtr pointer) { GCHandle gch = GCHandle.FromIntPtr(pointer); List<IntPtr> list = gch.Target as List<IntPtr>; if (list == null) { throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>"); } list.Add(handle); // You can modify this to check to see if you want to cancel the operation, then return a null here return true; } public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter); } "@ } } PROCESS{ foreach ($child in ([apifuncs]::GetChildWindows($MainWindowHandle))){ Write-Output (,([PSCustomObject] @{ MainWindowHandle = $MainWindowHandle ChildId = $child ChildTitle = (Get-WindowName($child)) })) } } }
You can directly associate it with the Get-Process result, for example:
Get-Process | Where-Object {$_.ProcessName -eq 'OUTLOOK'} | Get-ChildWindow