如何获取没有响应的前台应用程序的进程ID?

How to get the process Id of not responding foreground app?

我有一个监控用户当前正在工作的 window 的进程(GetForegroundWindow). To get process ID by HWND I use GetWindowThreadProcessId. But, if foreground app is hung, I will get the process Id of Desktop Window Manager - dwm.exe. I can determine is app hung by IsHungAppWindow但是如何获取前台挂起应用程序的真实进程 ID?

使用 C#,System.DiagnosticsSystem.Linq 你可以这样做:

List<IntPtr> handles = System.Diagnostics.Process.GetProcesses()
                                                 .Where(x => !x.Responding)
                                                 .Select(x => x.MainWindowHandle).ToList();

哪个 returns 没有响应的进程句柄。

我们可以使用 user32.dll HungWindowFromGhostWindow 中未记录的方法从 ghost 句柄中获取真正的 window 句柄(如果 windows 挂起,dwm 会创建其 ghost 副本)。

namespace HungProcessName
{
    using System.Runtime.InteropServices;
    using System.Threading;
    using System.Diagnostics;
    using System;

    class Program
    {
        [DllImport("user32.dll")]
        private static extern IntPtr GetForegroundWindow();
        [DllImport("user32.dll")]
        private static extern IntPtr GhostWindowFromHungWindow(IntPtr hwnd);
        [DllImport("user32.dll")]
        private static extern IntPtr HungWindowFromGhostWindow(IntPtr hwnd);
        [DllImport("user32.dll")]
        private static extern bool IsHungAppWindow(IntPtr hwnd);
        [DllImport("user32.dll")]
        private static extern uint GetWindowThreadProcessId(IntPtr hwnd, out uint procId);

        static void Main(string[] args)
        {
            while (true)
            {
                var hwnd = GetForegroundWindow();
                Console.WriteLine("Foreground window: {0}", hwnd);
                if (IsHungAppWindow(hwnd))
                {
                    var hwndReal = HungWindowFromGhostWindow(hwnd);
                    uint procId = 0;
                    GetWindowThreadProcessId(hwndReal, out procId);
                    if (procId > 0)
                    {
                        Process proc = null;
                        try { proc = Process.GetProcessById((int)procId); }
                        catch (Exception ex)
                        {
                            Console.WriteLine("Could not get proces with Id '{0}': {1}", procId, ex);
                        }
                        if (proc != null)
                        {
                            Console.WriteLine("Ghost hwnd: {0}, Real hwnd: {1}. ProcessId: {2}, Proccess name: {3}",
                                hwnd, hwndReal, procId, proc.ProcessName);
                        }
                    }
                }
                Thread.Sleep(100);
            }
        }
    }
}