AxWebBrowser 实现的多进程浏览器 (一)

我们使用 C#/VB.NET 进行 Trident 内核浏览器编程,大多都是单进程的,当打开的页面较多时比较容易出现卡死等情况。

单进程浏览器简单示例:

Public Class formBrowser
    Public WithEvents awb As New AxSHDocVw.AxWebBrowser
    Public isFirst As Boolean = True

    Private Sub formBrowser_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        awb.Dock = DockStyle.Fill
        Me.Controls.Add(awb)
        awb.Silent = True
        If isFirst Then awb.Navigate("http://www.geeuo.com")
    End Sub

    Private Sub awb_NewWindow3(sender As Object, e As AxSHDocVw.DWebBrowserEvents2_NewWindow3Event) Handles awb.NewWindow3
        Dim newForm As New formBrowser
        newForm.isFirst = False
        newForm.Show()
        e.ppDisp = newForm.awb.Application
    End Sub
End Class

  

从上面的代码可以看出,实现“多进程”的核心,可能就在 AxWebBrowser.NewWindow3 事件当中,在需要打开新的浏览器窗口时,我们只需要创建新的进程,并让新的网址页面在新的进程中打开,应该就可以了。

那么如何实现跨进程传递 AxWebBrowser.Application 对象呢?跨进程传递com对象貌似涉及到C++指针部分内容,实在太高深。

谷歌了一番发现可以通过“Internet Explorer_Server”句柄获取其所在的IWebBrowser2接口对象,而“IWebBrowser2”接口同样存在“Application”属性。

但是貌似 AxWebBrowser 并未实现 IWebBrowser2 接口?不管了,试试看行不行再说。

Declare Function ObjectFromLresult Lib "OLEACC.DLL" (ByVal lResult As Int32, ByRef riid As System.Guid, ByVal wParam As Int32, ByRef ppvObject As mshtml.IHTMLDocument) As Int32

<System.Runtime.InteropServices.DllImport("User32.dll")>
Public Shared Function RegisterWindowMessage(message As String) As Integer
End Function

<System.Runtime.InteropServices.DllImport("User32.dll")>
Public Shared Function SendMessageTimeout(hWnd As IntPtr, uMsg As Integer, wParam As IntPtr, lParam As IntPtr, fuFlags As Integer, uTimeout As Integer, ByRef lpdwResult As UIntPtr) As Integer
End Function

<System.Runtime.InteropServices.ComImport, System.Runtime.InteropServices.Guid("6d5140c1-7436-11ce-8034-00aa006009fa"), System.Runtime.InteropServices.InterfaceType(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIUnknown)>
Public Interface IServiceProvider
    Sub QueryService(ByRef guidService As Guid, ByRef riid As Guid, <System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Interface)> ByRef ppvObject As Object)
End Interface

<System.Runtime.InteropServices.DllImport("kernel32.dll")>
Public Shared Function LoadLibrary(lpLibFileName As String) As Integer
End Function


Public Shared Function GetIWebBrowser2(hwndInterneExplorer_Server As IntPtr) As SHDocVw.IWebBrowser2
    Dim IID_IWebBrowser2 As Guid = GetType(SHDocVw.IWebBrowser2).GUID
    Dim IID_IHTMLDocument2 As Guid = GetType(mshtml.IHTMLDocument2).GUID
    Dim SID_SWebBrowserApp As Guid = GetType(SHDocVw.IWebBrowserApp).GUID
    Dim doc2 As mshtml.IHTMLDocument2, web2 As SHDocVw.IWebBrowser2, tmpObj As Object
    doc2 = Nothing : web2 = Nothing : tmpObj = Nothing
    Try
        LoadLibrary("OLEACC.DLL")
        Dim nMsg As Integer = RegisterWindowMessage("WM_HTML_GETOBJECT")
        Dim lRes As UIntPtr = UIntPtr.Zero
        SendMessageTimeout(hwndInterneExplorer_Server, nMsg, New IntPtr(), New IntPtr(), &H2, 1000, lRes)  ' SMTO_ABORTIFHUNG = &H2
        If lRes.ToUInt32 <> 0 Then
            ObjectFromLresult(CInt(lRes.ToUInt32()), IID_IHTMLDocument2, 0, doc2)
            If doc2 IsNot Nothing Then
                System.Runtime.InteropServices.Marshal.GetIUnknownForObject(doc2)
                TryCast(doc2, IServiceProvider).QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, tmpObj)
                web2 = TryCast(tmpObj, SHDocVw.IWebBrowser2)
            End If
        End If
    Catch
    End Try
    Return web2
End Function

  

测试了一下,可以实现在新进程中打开新的页面,然而新页面并未与之前的页面共享 session。而且新页面的 referrer 也为空。

于是暂时以失败告终。

如果谁能解决,欢迎留言分享!

原文地址:https://www.cnblogs.com/hironpan/p/7634823.html