通过BHO获取url和HTMl,SetSite抛出异常

时间:2011-11-07 18:31:06

标签: c# com interop bho

我已经按照教程:http://www.15seconds.com/issue/040331.htm制作了一个BHO,但是我似乎并没有为我工作,我有来自考试的观察员代码,在那里她创建了实际的BHO,但当我尝试我的SetSite中的类型转换停止了,我怀疑我得到了例外。

这是我的示例代码,只是将它全部剥离,所以我得到了一个消息框。

[ClassInterfaceAttribute(ClassInterfaceType.None)]
    [GuidAttribute("0CD00297-9A19-4698-AEF1-682FBE9FE88D")]
    [ProgIdAttribute("Observer.BrowserMonitor")]
    public class BrowserMonitor: IObserver, IObjectWithSite
    {

        // HRESULT values used
        const int E_FAIL = unchecked((int)0x80004005);
        const int E_NOINTERFACE = unchecked((int)0x80004002);

        public BrowserMonitor()
        {

        }


        protected SHDocVw.IWebBrowser2 m_pIWebBrowser2; // the browser class object

        public void SetSite(object pUnkSite)
        {
            System.Windows.Forms.MessageBox.Show(pUnkSite.ToString());
            if (pUnkSite != null)
            {
                m_pIWebBrowser2 = pUnkSite as SHDocVw.IWebBrowser2;
            }
        }

        public void GetSite(ref System.Guid riid, out object ppvSite)
        {            
            System.Windows.Forms.MessageBox.Show("GetSite");
            ppvSite = null;
        }

        protected void DocumentComplete(object pDisp, ref object URL)
        {            
            System.Windows.Forms.MessageBox.Show("DocumentComplete");

        }

        protected bool ServiceEnabled()
        {
            return true;
        }

        protected void Release()
        {
            System.Windows.Forms.MessageBox.Show("Release");
        }

        protected void BeforeNavigate2(object pDisp, ref object url, ref object Flags, ref object TargetFrameName, 
            ref object PostData, ref object Headers, ref bool Cancel)
        {
            System.Windows.Forms.MessageBox.Show("BeforeNavigate2");
        }

        protected void OnQuit() 
        {
            try
            {
                System.Windows.Forms.MessageBox.Show("OnQuit");
            }
            catch{}
        }

        protected void NavigateComplete2(object pDisp, ref object URL)
        {
            System.Windows.Forms.MessageBox.Show("NavigationComplete2");            
        }

我的问题出在我的SetSite方法中,如何对任何类型的浏览器进行类型转换?如果我像现在一样运行这个样本,我只得到“GetSite”消息框,如果我删除了SetSite中的if句子,我也得到了SetSite。有谁知道怎么做?

1 个答案:

答案 0 :(得分:1)

  1. (对答案不重要)你真的不应该在C#中写一个BHO。是的,它可以做到,但这不是一个好主意。即使在.NET 4中使用SxS;为每个打开的选项卡初始化CLR的成本非常高。 (如果你坚持,那么你至少应该使用.NET 4。)

  2. Get / Set站点方法应根据IObjectWithSite的文档返回int。你的界面声明是错误的。

  3. 一旦修复界面,您的GetSite实现应如下所示:

    public int GetSite(ref Guid riid, out IntPtr ppvSite)
    {
        var pUnk = Marshal.GetIUnknownForObject(_pUnkSite);
        try
        {
            return Marshal.QueryInterface(pUnk, ref riid, out ppvSite);
        }
        finally
        {
            Marshal.Release(pUnk);
        }
    }
    

    在这种情况下,_pUnkSite是您在SetSite处获得的对象。所以SetSite看起来像这样:

    private object _pUnkSite;
    public int SetSite(object pUnkSite)
    {
        _pUnkSite = pUnkSite;
        //Cast pUnkSite to `IWebBrowser2` here and attach events.
        return 0;
    }
    

    一旦你最终得到了一些样板代码,你就可以将你的pUnkSite转换为像IWebBrowser2这样的东西来处理DOM。

  4. < shamelessplug>我知道写一个C#BHO是个坏主意because I have done so。我有一个样板GitHub项目here。< / shamelessplug>