在抛出未处理的JavaScript错误之前,不会查询IServiceProvider IElementBehaviorFactory

时间:2014-02-28 12:51:13

标签: c# .net webbrowser-control

我正在为.net WebBrowser控件提供自定义命名空间和二进制行为,并且在特定情况下它可以正常工作。使用以下代码,断点(标有)全部命中,我的命名空间已正确实现,并完成了以下行为:

int IServiceProvider.QueryService(ref Guid guidService, ref Guid riid, out IntPtr ppvObject)
{
    int hr = Native.E_NOINTERFACE;
    ppvObject = IntPtr.Zero;

    if (riid == IidClsid.IID_IElementBehaviorFactory)
    {
        // Returning S_OK tells the html host to query for our IHostBehaviorInit.
●       hr = Native.S_OK;
    }
    else if (riid == IidClsid.IID_IHostBehaviorInit)
    {
        ppvObject = Marshal.GetComInterfaceForObject(this, typeof(IHostBehaviorInit));
●       hr = Native.S_OK;
    }
    else if (guidService == IidClsid.IID_IInternetSecurityManager)
    {
        ppvObject = Marshal.GetComInterfaceForObject(this, typeof(IInternetSecurityManager));
●       hr = Native.S_OK;
    }
    return hr;
}

但是,由于测试页中的脚本错误,第一个和第二个断点仅被命中。如果我修复错误或抑制错误,断点永远不会命中。例如,以下代码阻止我的名称空间和行为被注册:

WebBrowser.Document.Window.Error += OnWebBrowserDocumentWindowError;

public void OnWebBrowserDocumentWindowError (object sender, IHTMLEventObj e)
{
    e.Handled = true;
}

这就是MSDN documentation for IHostBehaviorInit所说的:

  

MSHTML调用主机应用程序的IServiceProvider::QueryService来请求IElementBehaviorFactory接口,并向主机请求IHostBehaviorInit接口。如果IHostBehaviorInit接口可用,则MSHTML会调用IHostBehaviorInit::PopulateNamespaceTable方法。然后,宿主应用程序可以查询MSHTML以查找IElementNamespaceTable接口,并使用IElementNamespaceTable::AddNamespace方法将其他命名空间附加到命名空间表。

我注意到,如果我点击<select>打开下拉列表,第一个和第二个断点会突然发生。这真是奇怪的行为,任何人都可以帮我解决这个问题吗?

1 个答案:

答案 0 :(得分:2)

这可能不会直接回答这个问题,但对于一个简单的评论来说,它太冗长了。

为什么在前两种情况下比较riid而不是guidService?看起来像是一个错误,请改用guidService

此外,一旦您确定了所请求的服务,就不应该使用Marshal.GetComInterfaceForObject,因为riidguidService可能会有所不同。相反,请使用Marshal.GetIUnknownForObjectMarshal.QueryInterface

IntPtr unk = Marshal.GetIUnknownForObject(this);
try
{
    return Marshal.QueryInterface(unk, ref riid, out ppvObject);
}
finally
{
    Marshal.Release(unk);
}

此外,您实施IServiceProvider的方式可能会影响MSHTML如何选择。我建议您使用IProfferService。我有一个关于如何将IProfferServiceWebBrowser here一起使用的完整示例。