I have a multithreaded UI test tool that starts up instances of Internet Explorer. I would like to find a javascript alert box using the PInvoke API.
Finding it globally works fine:
IntPtr globalAlertHwnd = Pinvoke.FindWindow("#32770", "Message from webpage");
However, since I'm running multiple IE instances in parallel, I want to target the specific alert box based on its IE parent.
I can find it in the global pile of pointers as well:
IntPtr desktopHwnd = Pinvoke.GetDesktopWindow();
List<IntPtr> allDesktopChilds = Pinvoke.GetChildWindows(desktopHwnd).ToList();
bool match1 = allDesktopChilds.Any(hwnd => hwnd == globalAlertHwnd); // true
But as soon as I use the IE process, I can't find it. mainWindowHnadle
is IE's window handle.
List<IntPtr> ieChildren = Pinvoke.EnumerateProcessWindowHandles(mainWindowHnadle).ToList();
bool match2 = ieChildren.Any(hwnd => hwnd == globalAlertHwnd); // false
This is how EnumerateProcessWindowHandles
looks:
public static IEnumerable<IntPtr> EnumerateProcessWindowHandles(IntPtr hwnd)
{
List<IntPtr> handles = new List<IntPtr>();
uint processId;
GetWindowThreadProcessId(hwnd, out processId);
foreach (ProcessThread thread in Process.GetProcessById((int)processId).Threads)
{
EnumThreadWindows(thread.Id, (parentHwnd, lParam) =>
{
handles.Add(parentHwnd);
List<IntPtr> childHwnds = GetChildWindows(parentHwnd);
handles.AddRange(childHwnds);
return true;
}, IntPtr.Zero);
}
return handles;
}
public static List<IntPtr> GetChildWindows(IntPtr parent)
{
List<IntPtr> result = new List<IntPtr>();
GCHandle listHandle = GCHandle.Alloc(result);
try
{
Win32Callback childProc = new Win32Callback(EnumWindow);
EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
}
finally
{
if (listHandle.IsAllocated)
listHandle.Free();
}
return result;
}
I know that EnumChildWindows()
gets all children, not just the top level (verified by my second example).
I verified that the alert box exists in one of the IE threads, along with its OK button. Spy++ screenshot:
What am I missing? This method works fine in both Firefox and Chrome.
UPDATE:
It seems like this problem occurs because IE creates one process for the main window, and another process for each tab. I have to think about how to fetch the other process based on this.