2014-11-24 88 views
2

我想爲我們的Web測試服務器編寫一個實用程序,該服務器會殺死所有具有「始終位於頂部」窗口的進程。我想這是窗口樣式WS_EX_TOPMOST,但是,我不是100%確定。枚舉所有「始終位於頂部」的窗口

有沒有在C#的方式:

  • 列舉這些都是窗口「總在最前面」
  • ,並獲取相應的進程?
+0

所以,你想檢查每個進程,看看它是否有一個窗口總是在最前面的標誌? – Vajura 2014-11-24 09:05:28

+0

我寧願更高效,直接的方式。如果Windows不提供這種方式,我想我必須這樣做...... – 2014-11-24 09:09:17

+0

pinvoke EnumWindow並檢查WS_EX_TOPMOST – Maxwe11 2014-11-24 09:13:48

回答

3

下面是一個工作示例,它查找所有具有最頂層窗口的進程。但要小心:Windows資源管理器始終有一個最上面的窗口,你可能不想想要殺死該進程。

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以「始終保持最佳狀態」)。如果關注另一個窗口,大多數由您的方法找到的應用程序不會保持在最前。你偶然知道如何確定那些「永遠在頂部」窗口? – 2014-11-24 13:10:55

+0

我相信'WS_EX_TOPMOST'是正確的。請參閱http://msdn.microsoft.com/en-us/library/windows/desktop/ff700543%28v=vs.85%29.aspx此外,我們可能必須檢查窗口是否可見...我'米看着下一個... – helb 2014-11-24 13:15:03

+0

@ DR我添加了可見窗口的檢查。現在再試一次。 – helb 2014-11-24 13:20:07

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 2014-11-24 09:23:14

+0

@ hvd這正是我在我發佈的代碼下面注意到的。但是你是對的,那是一個可能不正確的假設。 – helb 2014-11-24 09:26:50

+0

啊,我誤讀你的筆記。並非所有不是主窗口的窗口都是子窗口。如果你想檢查所有的頂級窗口,你需要避免從進程的主窗口完全啓動。一個進程可能有多個頂級窗口,其中沒有任何其他子窗口。 – hvd 2014-11-24 09:29:25

相關問題