2016-07-28 4 views
-1

У меня есть процесс, который контролирует окно, которое пользователь в настоящее время работает (GetForegroundWindow). Чтобы получить идентификатор процесса по HWND, я использую GetWindowThreadProcessId. Но, если приложение на переднем плане висит, я получу идентификатор процесса Desktop Window Manager - dwm.exe. Я могу определить, что приложение висит на IsHungAppWindow. Но как получить реальный идентификатор процесса переднего плана?Как получить идентификатор процесса не отвечающего приложения переднего плана?

+0

ли с помощью 'System.Diagnostics.Process' Class вариант для вас? – user3185569

+0

@ user3185569, в чем преимущество System.Diagnostics.Process в моей ситуации? –

+0

Вы пытались отфильтровать файл dwm.exe? – Essigwurst

ответ

0

Мы можем использовать недокументированные методы из user32.dll HungWindowFromGhostWindow, чтобы получить реальный дескриптор окна из дескриптора (если окна висят, dwm создает свою копию-призрак). Undocumented functions: HungWindowFromGhostWindow and GhostWindowFromHungWindow

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); 
      } 
     } 
    } 
} 
+0

Почему мы хотим использовать этот недокументированный api? Вы высоко цените риски? Вы понимаете, что вы не должны это делать? И кто говорит, что у висячего окна есть окно-призрак. Часто они этого не делают. Процесс может отключить ореолы. Также окно может зависать и не быть призванным, потому что никто еще не пытался взаимодействовать с ним. –

+1

@ Давид Хеффернан, по крайней мере TaskManager [taskmgr.exe] [использует эту технику] (http://i67.tinypic.com/34dkl6f.png). Я дал тестовый код. Перед проверкой можно отправить [SendMessageTimeout] (https://msdn.microsoft.com/en-us//library/windows/desktop/ms644952 (v = vs.85) .aspx) с WM_NULL. Конечно, если кто-то назвал [DisableProcessWindowsGhosting] (https://msdn.microsoft.com/en-us/library/ms648415 (v = vs.85) .aspx), это не сработает. У вас есть идея? –

+0

Диспетчер задач - это часть оболочки. Конечно, он может использовать частные вызовы api. Вы не можете, хотя. Проблема в том, что мы не знаем, почему вы спрашиваете. Возможно, ваша настоящая проблема имеет другое решение. –

1

Ну с использованием C#, System.Diagnostics и System.Linq вы можете сделать это:

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

который возвращает дескрипторы процессов, которые не реагируют.

+0

Это даст идентификаторы процессов не отвечающих приложений. Но как сопоставить его с передним окном? –

+0

Должен ли я использовать Process.MainWindowHandle? –

+0

@ArtavazdBalayan ответ обновлен. – user3185569