2014-11-24 3 views
2

Я хочу написать утилиту для нашего веб-сервера тестирования, которая убивает все процессы, имеющие окно «всегда сверху». Я думаю, что это стиль окна WS_EX_TOPMOST, однако я не уверен на 100%.Перечислить все окна, которые «всегда сверху»

Есть ли способ в C#:

  • перечислить все окна, которые «всегда сверху»
  • и получить соответствующий процесс?
+0

Итак, вы хотите проверить каждый процесс и посмотреть, есть ли у него окно с флагом Always on Top? – Vajura

+0

Я предпочел бы более совершенный, прямой, путь. Если Windows не предоставляет такой способ, я думаю, я должен это сделать ... –

+0

pinvoke EnumWindow и проверка WS_EX_TOPMOST – Maxwe11

ответ

3

Вот рабочий пример, который находит все процессы, которые имеют самое верхнее окно. Будьте осторожны: Windows Explorer всегда имеет самое верхнее окно, и вы, вероятно, не должны хотите убить этот процесс.

class Program 
{ 
    const int WS_EX_TOPMOST = 0x00000008; 
    const int WS_VISIBLE = 0x10000000; 
    const int GWL_STYLE = -16; 
    const int GWL_EXSTYLE = -20; 

    static void Main(string[] args) 
    { 
     var topmostWindowHandles = new ArrayList(); 
     EnumWindows(EnumWindowsCallback, topmostWindowHandles); 

     var processesToKill = new HashSet<uint>(); 
     foreach (IntPtr hWnd in topmostWindowHandles) 
     { 
      uint processId = 0; 
      GetWindowThreadProcessId(hWnd, out processId); 
      processesToKill.Add(processId); 
     } 

     foreach (uint pid in processesToKill) 
     { 
      Process proc = Process.GetProcessById((int)pid); 
      Console.WriteLine("Killing " + proc.ProcessName); 
      // kill process, except explorer.exe 
     } 
    } 

    static bool EnumWindowsCallback(IntPtr hWnd, ArrayList lParam) 
    { 
     int exStyle = GetWindowLong(hWnd, GWL_EXSTYLE); 
     int style = GetWindowLong(hWnd, GWL_STYLE); 
     if ((exStyle & WS_EX_TOPMOST) == WS_EX_TOPMOST 
      && (style & WS_VISIBLE) == WS_VISIBLE) 
     { 
      lParam.Add(hWnd); 
     } 
     return true; 
    } 

    public delegate bool EnumWindowsProc(IntPtr hwnd, ArrayList lParam); 

    [DllImport("user32.dll")] 
    [return:MarshalAs(UnmanagedType.Bool)] 
    static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, ArrayList lParam); 

    [DllImport("user32.dll")] 
    static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); 

    [DllImport("user32.dll")] 
    static extern int GetWindowLong(IntPtr hWnd, int nIndex); 
} 
+0

Спасибо, отлично. Однако, я думаю, я неправильно понял 'WS_EX_TOPMOST'. Я ищу окна, которые не теряют фокус (например, VLC с «Stay always on top»). Большинство приложений, найденных вашим методом, не остаются на вершине, если другое окно сфокусировано. Знаете ли вы случайно, как определить только те, которые «остаются всегда сверху»? –

+0

'WS_EX_TOPMOST' верен, я верю. См. Http://msdn.microsoft.com/en-us/library/windows/desktop/ff700543%28v=vs.85%29.aspx Кроме того, нам, вероятно, нужно проверить, видно ли окно ... I ' m глядя в то, что следующий ... – helb

+0

@DR Я добавил проверку на видимые окна. Попробуйте еще раз. – helb

1

Вот решение, которое находит все процессы с самим верхним главным окном:

class Program 
{ 
    static void Main(string[] args) 
    { 
     int WS_EX_TOPMOST = 0x00000008; 
     int GWL_EXSTYLE = -20; 
     foreach (Process proc in Process.GetProcesses()) 
     { 
      IntPtr hWnd = proc.MainWindowHandle; 
      int res = GetWindowLong(hWnd, GWL_EXSTYLE); 
      if ((res & WS_EX_TOPMOST) == WS_EX_TOPMOST) 
      { 
       Console.WriteLine("Topmost window found for process " + proc.ProcessName); 
      } 
     } 
    } 

    [DllImport("user32.dll")] 
    static extern int GetWindowLong(IntPtr hWnd, int nIndex); 
} 

Это только проверяет, является ли главным окнопроцесса является верхним. Я оставляю этот ответ, потому что он может помочь с этой конкретной проблемой (найти самые главные окна).

+0

Предполагается, что необходимо проверить только основное окно процесса. Это предположение, которое может оказаться действительным, но оно ничем не подтверждается в вопросе, который я вижу. – hvd

+0

@hvd Вот что я заметил ниже кода, который я разместил. Но вы правы, это предположение, которое может быть неверным. – helb

+0

Ах, я неправильно прочитал вашу записку. Это не тот случай, когда все окна, которые не являются основным окном, являются дочерними окнами. Если вы хотите проверить все окна верхнего уровня, вам нужно будет полностью отказаться от основных окон процессов. Процесс может иметь несколько окон верхнего уровня, где ни один не является дочерним элементом любого другого. – hvd

Смежные вопросы