Comment utiliser EnumWindows pour rechercher des fenêtres avec une légende / un titre spécifique?

Je travaille sur une application qui deviendra éventuellement une API pour la conduite de tests d’interface utilisateur pour une application WPF.

À un moment du test initial sur lequel nous travaillons, nous obtenons 2 fenêtres contextuelles de sécurité Windows. Nous avons du code qui boucle 10 fois, il récupère le handle de l’un des popups en utilisant la méthode FindWindowByCaption, il entre les informations et clique OK.

9 fois sur 10, cela fonctionne très bien, mais nous voyons parfois ce qui semble être une condition de concurrence. Je soupçonne que la boucle commence quand une seule des fenêtres est ouverte et pendant qu’elle entre les informations, la seconde s’ouvre et vole le focus; après cela, il est suspendu indéfiniment

Ce que je me demande, c’est s’il existe une méthode pour obtenir toutes les poignées de fenêtre pour une légende donnée, de sorte que nous puissions attendre qu’il y en ait 2 avant de commencer la boucle.

Réponse originale

Utilisez EnumWindows et EnumWindows toutes les fenêtres, utilisez GetWindowText pour obtenir le texte de chaque fenêtre, puis filtrez-le comme vous le souhaitez.

 [DllImport("user32.dll", CharSet = CharSet.Unicode)] private static extern int GetWindowText(IntPtr hWnd, SsortingngBuilder strText, int maxCount); [DllImport("user32.dll", CharSet = CharSet.Unicode)] private static extern int GetWindowTextLength(IntPtr hWnd); [DllImport("user32.dll")] private static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam); // Delegate to filter which windows to include public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); ///  Get the text for the window pointed to by hWnd  public static ssortingng GetWindowText(IntPtr hWnd) { int size = GetWindowTextLength(hWnd); if (size > 0) { var builder = new SsortingngBuilder(size + 1); GetWindowText(hWnd, builder, builder.Capacity); return builder.ToSsortingng(); } return Ssortingng.Empty; } ///  Find all windows that match the given filter  ///  A delegate that returns true for windows /// that should be returned and false for windows that should /// not be returned  public static IEnumerable FindWindows(EnumWindowsProc filter) { IntPtr found = IntPtr.Zero; List windows = new List(); EnumWindows(delegate(IntPtr wnd, IntPtr param) { if (filter(wnd, param)) { // only add the windows that pass the filter windows.Add(wnd); } // but return true here so that we iterate all windows return true; }, IntPtr.Zero); return windows; } ///  Find all windows that contain the given title text  ///  The text that the window title must contain.  public static IEnumerable FindWindowsWithText(ssortingng titleText) { return FindWindows(delegate(IntPtr wnd, IntPtr param) { return GetWindowText(wnd).Contains(titleText); }); } 

Par exemple, pour obtenir toutes les fenêtres avec “Notepad” dans le titre:

 var windows = FindWindowsWithText("Notepad"); 

Win32Interop.WinHandles

Cette réponse s’est avérée assez populaire pour créer un projet OSS, Win32Interop.WinHandles, pour fournir une abstraction sur IntPtrs pour Windows Win32. En utilisant la bibliothèque, pour obtenir toutes les fenêtres contenant “Notepad” dans le titre:

 var allNotepadWindows = TopLevelWindowUtils.FindWindows(wh => wh.GetWindowText().Contains("Notepad")); 
 using HWND = IntPtr; /// Contains functionality to get all the open windows. public static class OpenWindowGetter { /// Returns a dictionary that contains the handle and title of all the open windows. /// A dictionary that contains the handle and title of all the open windows. public static IDictionary GetOpenWindows() { HWND shellWindow = GetShellWindow(); Dictionary windows = new Dictionary(); EnumWindows(delegate(HWND hWnd, int lParam) { if (hWnd == shellWindow) return true; if (!IsWindowVisible(hWnd)) return true; int length = GetWindowTextLength(hWnd); if (length == 0) return true; SsortingngBuilder builder = new SsortingngBuilder(length); GetWindowText(hWnd, builder, length + 1); windows[hWnd] = builder.ToSsortingng(); return true; }, 0); return windows; } private delegate bool EnumWindowsProc(HWND hWnd, int lParam); [DllImport("USER32.DLL")] private static extern bool EnumWindows(EnumWindowsProc enumFunc, int lParam); [DllImport("USER32.DLL")] private static extern int GetWindowText(HWND hWnd, SsortingngBuilder lpSsortingng, int nMaxCount); [DllImport("USER32.DLL")] private static extern int GetWindowTextLength(HWND hWnd); [DllImport("USER32.DLL")] private static extern bool IsWindowVisible(HWND hWnd); [DllImport("USER32.DLL")] private static extern IntPtr GetShellWindow(); } 

Et voici un code qui l’utilise:

 foreach(KeyValuePair window in OpenWindowGetter.GetOpenWindows()) { IntPtr handle = window.Key; ssortingng title = window.Value; Console.WriteLine("{0}: {1}", handle, title); } 

J’ai reçu ce code sur http://www.tcx.be/blog/2006/list-open-windows/

Si vous avez besoin d’aide pour utiliser ceci, faites-le moi savoir, je l’ai compris