2011-10-13 42 views
0

我正在学习从华廷它处理启动并连接到Internet Explorer下面的一段代码:华廷,IE浏览器启动和IWebBrowser2的窗口句柄

private static IEBrowser CreateIEPartiallyInitializedInNewProcess(Uri uri) 
    { 
     var m_Proc = CreateIExploreInNewProcess(uri); 
     var helper = new AttachToIeHelper(); 

     var action = new TryFuncUntilTimeOut(TimeSpan.FromSeconds(Settings.AttachToBrowserTimeOut)) 
     { 
      SleepTime = TimeSpan.FromMilliseconds(500) 
     }; 

     var ie = action.Try(() => 
     { 
      m_Proc.Refresh(); 
      var mainWindowHandle = m_Proc.MainWindowHandle; 

      // return mainWindowHandle != IntPtr.Zero ? GetIWebBrowser2Directly(mainWindowHandle) : null; 

      return mainWindowHandle != IntPtr.Zero 
       ? helper.FindIEPartiallyInitialized(new AttributeConstraint("hwnd", mainWindowHandle.ToString())) 
       : null; 
     }); 

     if (ie != null) return ie._ieBrowser; 
     // if (ie != null) return new IEBrowser(ie); 

     throw new BrowserNotFoundException("IE", "Timeout while waiting to attach to newly created instance of IE.", Settings.AttachToBrowserTimeOut); 
    } 

什么华廷做的是,它启动Internet Explorer和等待直到它得到它.MainWindowHandle(这是“窗口”在Internet Explorer中显示内容的句柄)。一旦获得了该窗口句柄的保留,它就会获得在用户桌面上运行的所有IWebBrowser2窗口的列表,并尝试将该进程的.MainWindowHandle与一个(如果有的话)源自窗口句柄的窗口句柄IWebBrowser2集合。

这种方法最显著的问题是,IWebBrowser2.HWND财产(以比较.MainWindowHandle需要)可非常问题,不稳定,因为它引发InvalidCastException每个其他时间,当您试图访问的气质感它(至少在我正在运行的机器上进行测试)。然后再次有这种操作的开销。

这里是我的问题,任何人都可能更知识渊博,我在Windows编程:因为HWNDs会匹配反正为什么我们不使用.MainWindowHandle值从蝙蝠检索所需的IWebBrowser2(请参阅以上注释的代码)通过使用以下方法(由华廷本身使用内部ShellWindow2.cs)的代码启发:

private static IWebBrowser2 GetIWebBrowser2Directly(IntPtr embeddedWebBrowserWindowHandle) 
    { 
     IHTMLDocument2 document2 = UtilityClass.TryFuncIgnoreException(() => IEUtils.IEDOMFromhWnd(embeddedWebBrowserWindowHandle)); 
     if (document2 == null) return null; 

     IHTMLWindow2 parentWindow = UtilityClass.TryFuncIgnoreException(() => document2.parentWindow); 
     if (parentWindow == null) return null; 

     return UtilityClass.TryFuncIgnoreException(() => ShellWindows2.RetrieveIWebBrowser2FromIHtmlWindw2Instance(parentWindow)); 
    } 

(作为旁注,我们甚至可以使一个代理对象,在我的另一个交描述,以缓存窗口句柄,以避免询问IWebBrowser2.HWND)。

这对我来说工作得很好。我看不到任何HWND之间的冲突或不匹配 - 不知道是否有我可能错过的一个角落案例。我很想在WatiN论坛上询问这个问题,但我想先在程序员中心问一下,以防万一我错过了一些明显的东西。

谢谢大家提前。任何提示赞赏。

干杯, 多米尼克

回答

1

我开始挖掘到Internet Explorer的内部窗口结构,并与下面的层次上来(不相关的窗口ofcourse中省略):

IEFrame
|
- TabWindowClass-1 --convert - > FirstIWebBrowser2
|
- TabWindowClass-2 --convert - > SecondIWebBrowser2
|
...
|
- TabWindowClass-第N - 转换 - >第N-的IWebBrowser2

通过测试,我想出了在Windows7 + IE9以下的见解(9.0.8112.16421)

  1. 有趣的是(并反直觉地)IWebBrowser2.HWND与从它来的TabWindowClass的HWND是不一样的。

  2. IEFrame-> HWND与任何IWebBrowser2相同。HWND属性在同一个Internet Explorer进程中。即使我们在同一个Internet Explorer进程中打开了多个选项卡,情况也是如此。

  3. Internet Explorer进程的Process.MainWindowHandle属性(当我们以编程方式启动Internet Explorer时)与IEFrame-> HWND相同,因此也与IWebBrowser2对象的属性相同。

  4. 通过立即使用IEFrame的HWND(使用我在原始文章中概述的方法)可以检索活动的选项卡。

我最好的猜测,为什么上述HWND布局认为是:

  1. 无论是乡亲在微软做出IEFrame和的IWebBrowser2之间的HWND布线,因为其实这里只有1个活动标签窗口(同时用户被给出X个标签的错觉)。还是......

  2. 因为有必要保持向后兼容针对IE浏览器的早期版本中已存在的代码兼容性和代码使用IEFrame的HWND得到它的IWebBrowser2对象。

在这两种情况下,我觉得,当它涉及到从IWebBrowser2接口导致InvalidCastException的访问也有可能是在这个HWND布线实施了内部错误。

任何人如果对这个问题有更多的了解,请随时放下一两行。希望这些帮助。

干杯, Dominick