C# 除非抛出未处理的JavaScript错误,否则不会查询IServiceProvider IElementBehaviorFactory
我为.NETWebBrowser控件提供了一个自定义名称空间和二进制行为,它在特定情况下运行良好。使用以下代码,断点(标记为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;
●代码>)所有命中和我的命名空间均正确实现,并完成以下行为:
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);
}