2011-10-13 72 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