【发布时间】: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 事件:
- 新窗口/标签打开
- 新域已连接(可能是新的保持连接?)
- 实际下载
显然我只想要实际下载事件的偶数。
【问题讨论】:
标签: c++ windows internet-explorer bho wininet