How can I get all window handles by a process in Powershell?

后端 未结 1 1401
[愿得一人]
[愿得一人] 2020-12-09 20:03

I have this script

Get-Process | Where-Object {$_.MainWindowTitle -like \"*total*\"}  

Which yield this information

Handles         


        
相关标签:
1条回答
  • 2020-12-09 20:43

    First, you should check out WASP and see if it suits your needs: http://wasp.codeplex.com/

    Secondly, I have modified 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 a MainWindowHandle as input, and will give you an object with child handle IDs back (It will also list any window titles, if any).

    I hope one of these methods will give 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 pipe it directly from the result of Get-Process, like this:

    Get-Process | Where-Object {$_.ProcessName -eq 'OUTLOOK'} | Get-ChildWindow
    
    0 讨论(0)
提交回复
热议问题