【问题标题】:Getting url and HTMl through a BHO, SetSite throws an exception通过BHO获取url和HTMl,SetSite抛出异常
【发布时间】:2011-12-23 20:43:38
【问题描述】:

我已按照以下教程操作:http://www.15seconds.com/issue/040331.htm 制作 BHO,但我似乎不适合我,我有示例中的 Observer 代码,她在其中创建了实际的 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。有谁知道怎么做?

【问题讨论】:

  • 如果我删除“if”,只留下消息框,它会显示消息框。如果我离开“if”结构,我什至不会弹出消息框

标签: c# com interop bho


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

  2. 根据 IObjectWithSite 的文档,Get / Set 站点方法应返回一个 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. 我知道编写 C# BHO 是个坏主意 because I have done so。我有一个样板 GitHub 项目here

【讨论】:

  • 但它不是 SetSite 我正在寻找将类型转换为网络浏览器以连接到导航事件。当我阅读 tuts 时,GetSite 在加载后被调用,以便在需要时释放?
  • @H4mm3rHead 您的 C# 接口需要与 COM IDL 的定义相匹配。如果事情没有正确排列,.NET 会出现编组错误。
  • 刚刚将这两种方法都更改为 int,并使实现返回 0(零) - 这导致我的 IExplorer 挂起,没有任何回复,在此更改之前我得到了我的消息框
  • 新版本:查看你的 tut,我关注的那个在界面中没有用户 [PreserveSig],现在我做了并更改了返回 int 的方法,一切正常(使用返回类型),我得到了我的消息框 - 仍然没有类型转换
  • @H4mm3rHead GetSite 不应返回零。请参阅我更新的代码示例。
猜你喜欢
  • 2013-06-24
  • 2015-06-24
  • 2021-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多