我正在开发一个应用程序,最终将成为推动WPF应用程序UI测试的API.
在我们正在进行的初始测试的一个点上,我们得到2个Windows安全弹出窗口.我们有一些循环10次的代码,它使用FindWindowByCaption方法获取其中一个弹出窗口的句柄并输入信息并单击确定.
10次中有9次可以正常运行,但我们偶尔会看到看起来像是一场比赛的情况.我的怀疑是,当只有一个窗口打开时,循环开始,而当它输入信息时,第二个窗口打开并窃取焦点; 在此之后它只是无限期地挂起.
我想知道的是,如果有任何方法来获取给定标题的所有窗口句柄,那么我们可以等到2开始循环之前.
Fri*_*Guy 78
使用EnumWindows并枚举所有窗口,使用GetWindowText获取每个窗口的文本,然后根据需要过滤它.
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder 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);
/// <summary> Get the text for the window pointed to by hWnd </summary>
public static string GetWindowText(IntPtr hWnd)
{
int size = GetWindowTextLength(hWnd);
if (size > 0)
{
var builder = new StringBuilder(size + 1);
GetWindowText(hWnd, builder, builder.Capacity);
return builder.ToString();
}
return String.Empty;
}
/// <summary> Find all windows that match the given filter </summary>
/// <param name="filter"> A delegate that returns true for windows
/// that should be returned and false for windows that should
/// not be returned </param>
public static IEnumerable<IntPtr> FindWindows(EnumWindowsProc filter)
{
IntPtr found = IntPtr.Zero;
List<IntPtr> windows = new List<IntPtr>();
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;
}
/// <summary> Find all windows that contain the given title text </summary>
/// <param name="titleText"> The text that the window title must contain. </param>
public static IEnumerable<IntPtr> FindWindowsWithText(string titleText)
{
return FindWindows(delegate(IntPtr wnd, IntPtr param)
{
return GetWindowText(wnd).Contains(titleText);
});
}
Run Code Online (Sandbox Code Playgroud)
例如,要在标题中使用"记事本"获取所有窗口:
var windows = FindWindowsWithText("Notepad");
Run Code Online (Sandbox Code Playgroud)
这个答案非常受欢迎,我创建了一个OSS项目Win32Interop.WinHandles,为win32窗口提供了IntPtrs的抽象.使用该库,获取标题中包含"记事本"的所有窗口:
var allNotepadWindows
= TopLevelWindowUtils.FindWindows(wh => wh.GetWindowText().Contains("Notepad"));
Run Code Online (Sandbox Code Playgroud)