2

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:

enter image description here

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.

Johan
  • 35,120
  • 54
  • 178
  • 293

1 Answers1

1

Solved by forcing IE to create a single process for each instance:

Create or update registry key TabProcGrowth in HKEY_CURRENT_USER\Software\MicrosoftInternet Explorer\Main. It should be a REG_DWORD 32 bit with value 0.

Johan
  • 35,120
  • 54
  • 178
  • 293