为了能够过滤使用 C# Web 浏览器 (WinForms) 获取的 URL(包括 JS、图像等),唯一可包含的选项似乎是包装 HTTP 的异步可插入协议(以及后来的其他协议)。不幸的是,在几次调用后InvalidCastException
,原始协议实现抛出了一个失败,这也是奇怪的部分,它似乎在失败之前成功了几次。
现在一些代码:
首先注册并附加协议的工厂:
var ep = new FilteredHttpProtocolFactory();
Guid id = Guid.Parse ("E00957BD-D0E1-4eb9-A025-7743FDC8B27B");
session.RegisterNameSpace (ep, ref id, "http", 0, null, 0);
(工厂:)
[Guid ("EF474615-8079-4CFA-B114-6D1D28634DD8")]
[ComVisible (true)]
[ClassInterface (ClassInterfaceType.None)]
public class FilteredHttpProtocolFactory : IClassFactory
{
public void CreateInstance (object pUnkOuter, Guid riid, out object ppvObject)
{
ppvObject = new FilteredHttpProtocol();
}
public void LockServer (bool fLock)
{
}
}
这是 IE 使用的原始 HTTP 协议,当使用它而不是包装器时,它工作得很好:
[ComImport]
[Guid ("79eac9e2-baf9-11ce-8c82-00aa004ba90b")]
public class OriginalHttpHandler
{
}
这是包装器本身:
[Guid ("E00957BD-D0E1-4eb9-A025-7743FDC8B27B")]
[ComVisible (true)]
[ClassInterface (ClassInterfaceType.None)]
[AsyncProtocol (Name = "http2", Description = "blah")]
public class FilteredHttpProtocol : IInternetProtocol, IInternetProtocolRoot
{
private readonly IInternetProtocol _wrapped;
public FilteredHttpProtocol ()
{
var originalHttpHandler = new OriginalHttpHandler();
_wrapped = (IInternetProtocol) originalHttpHandler;
}
public void Start (string szURL, IInternetProtocolSink Sink, IInternetBindInfo pOIBindInfo, uint grfPI, uint dwReserved)
{
_wrapped.Start (szURL, Sink, pOIBindInfo, grfPI, dwReserved);
}
public void Continue (ref _tagPROTOCOLDATA pProtocolData)
{
_wrapped.Continue (ref pProtocolData); // <- FAILS HERE
}
// .... other methods from IInternetProtocol
public uint Read (IntPtr pv, uint cb, out uint pcbRead)
{
return _wrapped.Read (pv, cb, out pcbRead); // <- OR HERE
}
}
所以,奇怪的部分是,构造函数被调用,Start()
被调用,甚至被调用多次,直到页面的部分已经可见(!)时整个事情失败(使用Read()
或),但似乎主要是一个缺少特定图像(主要是!):Continue()
Read()
Continue()
Unable to cast COM object of type 'Clients.Windows.Protocol.OriginalHttpHandler'
to interface type 'Clients.Windows.Protocol.IInternetProtocol'. This operation
failed because the QueryInterface call on the COM component for the interface
with IID '{79EAC9E4-BAF9-11CE-8C82-00AA004BA90B}' failed due to the following
error: No such interface supported (Exception from HRESULT: 0x80004002 E_NOINTERFACE)).
看到我已经多次将对象强制转换为所述接口(这应该导致QueryInterface()
每次调用,并且在失败之前已经多次调用它(通过断点等进行验证),这个错误真的很令人费解。通过查看参考计数我已经排除了过早处置的对象(无论如何都没有意义)。
我尝试了几件事:
- 谷歌,但应用程序相当罕见
- http://msdn.microsoft.com/en-us/library/aa767916(v=vs.85).aspx
- 继承 ComImport 的对象 - 然后我的实现被忽略
- 查看参考计数
- 各种演员表
- 检查 GUID 和接口是否有错误
- 询问同事
基本上,我想要实现的是包装 IE 的默认 http 协议实现以过滤掉 URL,包括从中检索资源的 URL。我也会对合适的替代方案感到满意,但它们必须符合 GPLv2,可与浏览器应用程序一起部署,并且不对系统的其余部分进行任何更改(即无代理)。
谢谢你的帮助 ;)
顺便说一句,这将成为我硕士论文的一部分:http: //desktopgap.codeplex.com