C# 除非抛出未处理的JavaScript错误,否则不会查询IServiceProvider IElementBehaviorFactory

C# 除非抛出未处理的JavaScript错误,否则不会查询IServiceProvider IElementBehaviorFactory,c#,.net,webbrowser-control,C#,.net,Webbrowser Control,我为.NETWebBrowser控件提供了一个自定义名称空间和二进制行为,它在特定情况下运行良好。使用以下代码,断点(标记为●)所有命中和我的命名空间均正确实现,并完成以下行为: int IServiceProvider.QueryService(ref Guid guidService, ref Guid riid, out IntPtr ppvObject) { int hr = Native.E_NOINTERFACE; ppvObject = IntPtr.Zero;

我为.NETWebBrowser控件提供了一个自定义名称空间和二进制行为,它在特定情况下运行良好。使用以下代码,断点(标记为
)所有命中和我的命名空间均正确实现,并完成以下行为:

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;

MSDN是这样说的:

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


我注意到,如果我点击
打开下拉列表,第一个和第二个断点会突然出现。这真是奇怪的行为,有人能帮我弄清楚吗?

这可能不能直接回答这个问题,但它太长了,不适合简单的评论

为什么在前两种情况下比较
riid
而不是
guidService
?在我看来这是一个bug,请改用
guidService

此外,一旦确定了所请求的服务,就不应该使用
Marshal.getcointerfaceforobject
,因为
riid
guidService
可能不同。相反,使用
Marshal.getiunknownfobject
Marshal.QueryInterface

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

另外,实现IServiceProvider的方式可能会影响MSHTML获取它的方式。我建议你用这个。我有一个完整的例子,说明了如何将
IProfferService
WebBrowser

一起使用
FEATURE\u BROWSER\u EMULATION
的IE版本和价值,如果有的话?您是否尝试过禁用
功能\u行为
(将其设置为
0
)?@Noseratio:IE版本为10,但文档模式为IE 7<此应用程序的代码>功能\u浏览器\u仿真
设置为
7000
(出于兼容性原因)<代码>功能\u行为设置为
1
(默认值),但将其更改为
0
没有任何区别。Andy,您可能希望将此作为错误报告给Microsoft,尽管可能无法解决。自从IE10以来,他们一直在反对二进制行为,而IE11对二进制行为的支持更差。@Noseratio:再次感谢您的帮助。在IE 10和IE 11中,二元行为有效吗?没问题,我希望我能帮助得更好。当
FEATURE\u BROWSER\u EMULATION
设置为IE9或更低版本,并且当出现问题时,它们仍然可以工作。我不相信他们会继续在IE12中工作。谢谢,我已经做了你推荐的更改。我在玩
riid
/
guidService
变量,但在问这个问题之前忘了将它们更改回去。有趣的是,我会在有机会的时候检查一下,然后再联系你。嗯,这并没有解决问题,但你的回答非常有用。让赏金点数白白浪费是没有意义的:-)
IntPtr unk = Marshal.GetIUnknownForObject(this);
try
{
    return Marshal.QueryInterface(unk, ref riid, out ppvObject);
}
finally
{
    Marshal.Release(unk);
}