¿Cómo enumerar todas las ventanas que pertenecen a un proceso particular usando .NET?

Resuelto Salvador asked hace 14 años • 3 respuestas

¿Cómo puedo encontrar todas las ventanas creadas por un proceso particular usando C#?

ACTUALIZAR

Necesito enumerar todas las ventanas que pertenecen a un proceso en particular utilizando el PID (ID de proceso) de una aplicación.

Salvador avatar Mar 28 '10 10:03 Salvador
Aceptado
delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);

[DllImport("user32.dll")]
static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn,
    IntPtr lParam);

static IEnumerable<IntPtr> EnumerateProcessWindowHandles(int processId)
{
    var handles = new List<IntPtr>();

    foreach (ProcessThread thread in Process.GetProcessById(processId).Threads)
        EnumThreadWindows(thread.Id, 
            (hWnd, lParam) => { handles.Add(hWnd); return true; }, IntPtr.Zero);

    return handles;
}

y uso de muestra:

private const uint WM_GETTEXT = 0x000D;

[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam, 
    StringBuilder lParam);

[STAThread]
static void Main(string[] args)
{
    foreach (var handle in EnumerateProcessWindowHandles(
        Process.GetProcessesByName("explorer").First().Id))
    {
        StringBuilder message = new StringBuilder(1000);
        SendMessage(handle, WM_GETTEXT, message.Capacity, message);
        Console.WriteLine(message);
    }
}
Konstantin Spirin avatar Apr 06 '2010 12:04 Konstantin Spirin

Utilice la API de Win32 EnumWindows (si desea ventanas secundarias EnumChildWindows ) o, alternativamente, puede utilizar EnumThreadWindows .

[DllImport("user32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool EnumWindows(EnumThreadWindowsCallback callback, IntPtr extraData);

Luego verifique a qué proceso pertenece cada ventana usando la API de Win32 GetWindowThreadProcessId

[DllImport("user32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern int GetWindowThreadProcessId(HandleRef handle, out int processId);
Brian R. Bondy avatar Mar 28 '2010 03:03 Brian R. Bondy

Hilo antiguo, pero me ayudó a comenzar, así que aquí hay una pequeña función de utilidad que encontrará una ventana secundaria que coincida con una lambda (predicado). Ser fácil de cambiar para devolver una lista. Se manejan múltiples criterios en el predicado.

    public delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam);

    [DllImport("user32.Dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool EnumChildWindows(IntPtr parentHandle, Win32Callback callback, IntPtr lParam);

    /// <summary>
    /// Find a child window that matches a set of conditions specified as a Predicate that receives hWnd.  Returns IntPtr.Zero
    /// if the target window not found.  Typical search criteria would be some combination of window attributes such as
    /// ClassName, Title, etc., all of which can be obtained using API functions you will find on pinvoke.net
    /// </summary>
    /// <remarks>
    ///     <para>Example: Find a window with specific title (use Regex.IsMatch for more sophisticated search)</para>
    ///     <code lang="C#"><![CDATA[var foundHandle = Win32.FindWindow(IntPtr.Zero, ptr => Win32.GetWindowText(ptr) == "Dashboard");]]></code>
    /// </remarks>
    /// <param name="parentHandle">Handle to window at the start of the chain.  Passing IntPtr.Zero gives you the top level
    /// window for the current process.  To get windows for other processes, do something similar for the FindWindow
    /// API.</param>
    /// <param name="target">Predicate that takes an hWnd as an IntPtr parameter, and returns True if the window matches.  The
    /// first match is returned, and no further windows are scanned.</param>
    /// <returns> hWnd of the first found window, or IntPtr.Zero on failure </returns>
    public static IntPtr FindWindow(IntPtr parentHandle, Predicate<IntPtr> target) {
        var result = IntPtr.Zero;
        if (parentHandle == IntPtr.Zero)
            parentHandle = Process.GetCurrentProcess().MainWindowHandle;
        EnumChildWindows(parentHandle, (hwnd, param) => {
            if (target(hwnd)) {
                result = hwnd;
                return false;
            }
            return true;
        }, IntPtr.Zero);
        return result;
    }

Ejemplo

var foundHandle = Win32.FindWindow(IntPtr.Zero, ptr => Win32.GetWindowText(ptr) == "Dashboard");
Wade Hatler avatar May 15 '2014 21:05 Wade Hatler