IE BHO - 为页面加载调用 DISPID_FILEDOWNLOAD?

Posted

技术标签:

【中文标题】IE BHO - 为页面加载调用 DISPID_FILEDOWNLOAD?【英文标题】:IE BHO - DISPID_FILEDOWNLOAD being called for page loads? 【发布时间】:2014-08-17 11:08:12 【问题描述】:

我正在实现一个 Internet Explorer 浏览器帮助对象,该对象应该捕获 DISPID_FILEDOWNLOAD 事件。

我首先在 C# 中实现了这个,效果很好,只是我还需要与 URL 一起使用的 cookie,因此需要调用 InternetGetCookiesEx。由于 .NET 在它自己的进程中运行,它不会向我返回会话 cookie,所以不好。

然后我用 C++ 编写了一个快速测试 DLL,以便将其加载到与 IE 相同的进程中,这对 cookie 非常有用,但我现在遇到了一个新问题:

当我只希望它们用于实际下载时,我在我的 Invoke 函数中为每个页面加载调用 DISPID_FILEDOWNLOAD

在 C# 版本中,我只接到了对 WebBrowser.FileDownload 的调用以进行实际下载,但似乎 C++ 版本甚至在每次页面加载时都会发送 DISPID_FILEDOWNLOAD。

STDMETHODIMP CIEHlprObj::Invoke(
    DISPID dispidMember, 
    REFIID riid, 
    LCID lcid, 
    WORD wFlags,
    DISPPARAMS* pDispParams, 
    VARIANT* pvarResult,
    EXCEPINFO*  pExcepInfo,  
    UINT* puArgErr
    )

   USES_CONVERSION;

   if (!pDispParams)
      return E_INVALIDARG;

   LPOLESTR lpURL = NULL;
   m_spWebBrowser2->get_LocationURL(&lpURL);

   int i = 0;
   switch (dispidMember)
   
      case DISPID_BEFORENAVIGATE2:
      case DISPID_BEFORENAVIGATE:

         sCurrentFile=NULL;

         if (pDispParams->cArgs >= 5 && pDispParams->rgvarg[5].vt == (VT_BYREF | VT_VARIANT))
         
             CComVariant varURL(*pDispParams->rgvarg[5].pvarVal);
             varURL.ChangeType(VT_BSTR);

             char* myStr = OLE2T(varURL.bstrVal);
             if (myStr)
             
                sCurrentFile = AllocateString(myStr);
                sCurrentFileW = varURL.bstrVal;
             
         

         break;

      case DISPID_FILEDOWNLOAD:

          // CALLED FOR EACH PAGE LOAD!

          if(sCurrentFile)
          
              TCHAR cookies[8192];
              DWORD size = 8192;

              BOOL ret = InternetGetCookieEx(sCurrentFile,
                  0,
                  cookies,
                  &size,
                  INTERNET_COOKIE_HTTPONLY,
                  0);

              ::MessageBox(0, sCurrentFile, "Downloading called multiple times!!", MB_OK);
          
          break;

      default:
         break;
   

   return S_OK;

是否有一些过滤器需要在某处检查以了解 DISPID_FILEDOWNLOAD 事件是否与文件加载或实际文件下载相关?

非常感谢

更新:

仔细观察,似乎 C# 托管代码版本实际上也在做同样的事情,只是我第一次没有注意到它。

似乎在以下情况下调用了 FileDownload 事件:

    新窗口/标签打开 新域已连接(可能是新的保持连接?) 实际下载

显然我只想要实际下载事件的偶数。

【问题讨论】:

【参考方案1】:

作为一个可能的解决方案,我注意到 MS 提供了一个 ActiveDocument (BOOL) 参数以及事件。根据 Microsoft 文档,ActiveDocument 参数的含义是:

一个布尔值,指定文件是否为活动文档

http://msdn.microsoft.com/en-us/library/bb268220(v=vs.85).aspx

不是很有帮助,但如果我将 DISPID_FILEDOWNLOAD 事件记录到文本文件并稍后查看它们,似乎我应该忽略 ActiveDocument = true 的所有事件

获取参数非常简单:

BOOL cancel = *pDispParams->rgvarg[0].pboolVal;
BOOL active = pDispParams->rgvarg[1].boolVal;

所以代码只需要更新为:

if (active)
    return S_OK;

我只能假设这是 IE 发送的某个事件,告诉 BHO 一个页面正在下载.. 不是一个文件,尽管这应该意味着我在每个页面加载时都会收到一个 DISPID_FILEDOWNLOAD 事件,但我没有.. 只有新的标签/浏览器实例和一些新的连接。

希望其他人能够为此做出贡献并阐明处理此问题的最佳方法是什么,因为这感觉有点像 hack。

【讨论】:

以上是关于IE BHO - 为页面加载调用 DISPID_FILEDOWNLOAD?的主要内容,如果未能解决你的问题,请参考以下文章

在IE的管理加载项里有个这个BHO.BrowserMonitor,请问是啥东西?

ActiveX 或 BHO(Internet Explorer)

Delphi 网络调试助手 源码

在BHO中处理JavaScript生成的页面

使用 IE 插件 Browser Helper Object (BHO) 在 iframe 中访问正文(至少一些数据)

BHO:onload 完成执行时收到通知