全局HOOK与IE接口 0x8001010D错误

nmg1852951 2010-07-20 07:32:13
最近在做一个自动测试工具,在做到web部分的时候,需要从浏览器窗体中去获取IHTMLDocument2接口以获得所操作的控件的信息,但是遇到一个0x8001010D错误,错误信息为 First-chance exception at 0x75a29617 in Hook.exe: 0x8001010D: 因为应用程序正在发送一个输入同步呼叫,所以无法执行传出的呼叫。
我的在全局鼠标钩子的回调函数中使用以下代码:
IHTMLDocument2* GetDocInterface(HWND hWnd)
{
// 我们需要显示地装载OLEACC.DLL,这样我们才知道有没有安装MSAA
CoInitialize( NULL );
HINSTANCE hInst = ::LoadLibrary( _T("OLEACC.DLL") );
IHTMLDocument2* pDoc2=NULL;
if ( hInst != NULL ){
if ( hWnd != NULL ){
CComPtr<IHTMLDocument> spDoc=NULL;
LRESULT lRes;

UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );
/*clock_t time = clock();
CString strTime;
strTime.Format(_T("%d"),time);
OutputDebugString(strTime);*/
OutputDebugString(_T("Before SendMessage \n"));
int re = ::SendMessageTimeout( hWnd, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*)&lRes );
CString result;
result.Format(_T("SendMessage re:%d \n"),re);
OutputDebugString(result);
LPFNOBJECTFROMLRESULT pfObjectFromLresult = (LPFNOBJECTFROMLRESULT)::GetProcAddress( hInst, "ObjectFromLresult" );
OutputDebugStringA("getAddress \n");
if ( pfObjectFromLresult != NULL )
{
HRESULT hr;
//hr = ObjectFromLresult(lRes,IID_IHTMLDocument,0,(void**)&spDoc);
hr=(*pfObjectFromLresult)( lRes, IID_IHTMLDocument, 0, (void**)&spDoc );
OutputDebugStringA("Get Object:");
if ( SUCCEEDED(hr) ){
OutputDebugStringA(" Success !\n");
CComPtr<IDispatch> spDisp;
CComQIPtr<IHTMLWindow2> spWin;
spDoc->get_Script( &spDisp );
spWin = spDisp;
spWin->get_document( &pDoc2 );
}
else
{
OutputDebugStringA("Fail ! \n");
}
}
}
::FreeLibrary(hInst);
}
else{//如果没有安装MSAA
//MessageBox(_T("请您安装Microsoft Active Accessibility"));
}
char PDoc2[100];
CString temp = _T("the return value is :");
temp += itoa((int)pDoc2,PDoc2,16);
OutputDebugString(temp + _T("\n"));
CoUninitialize();
return pDoc2;
}
代码是在执行到hr=(*pfObjectFromLresult)( lRes, IID_IHTMLDocument, 0, (void**)&spDoc );的时候,发生了0x8001010D的错误,所以从VS2008的输出窗口上可以看到如下信息:
First-chance exception at 0x75a29617 in Hook.exe: 0x8001010D: 因为应用程序正在发送一个输入同步呼叫,所以无法执行传出的呼叫。.
Get Object:Fail !
我想问下,这个错误是由全局钩子造成的么?因为在我不用Hook,而是通过别的窗体事件来激发上面的GetDocInterface函数,这段代码可以正确的执行。
想请教有做过类似的项目的大哥给点提示,告诉我错误的原因。小弟万分感谢
...全文
271 点赞 收藏 12
写回复
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
nmg1852951 2010-08-14
算了,虽然还不知道原因,但是好歹有解决方案了,这样结贴吧
回复
a220315410 2010-08-04
还没解决啊,再帮你顶下
回复
nmg1852951 2010-08-03
这个问题暂时还没解决,但是,上次突发奇想,将WH_MOUSE_LL的钩子替换成WH_MOUSE后,发现不在发生冲突。
思考了下并试验了一下,使用WH_MOUSE_LL钩子,回调函数的DLL不会被注入到目标线程,而是在安装钩子的线程中执行的。而WH_MOUSE钩子的回调函数的DLL会被注入到目标线程中,由目标线程来执行。这个区别大概是为什么WH_MOUSE_LL钩子写在EXE中也能安装全局钩子,而WH_MOUSE钩子只有写在DLL中才能安装全局钩子的原因吧。
之前产生冲突的原因,尚未明确,有待考证。根据我的猜想,WH_MOUSE_LL的钩子安装为全局钩子后,被监控的线程收到鼠标消息后,会把自己的鼠标消息send给安装鼠标钩子的线程,所以当执行
hr=(*pfObjectFromLresult)( lRes, IID_IHTMLDocument, 0, (void**)&spDoc );
的时候发生的线程访问冲突,而使用WH_MOUSE之后,被监控的线程(也就是IE)自己执行了
hr=(*pfObjectFromLresult)( lRes, IID_IHTMLDocument, 0, (void**)&spDoc );
就不存在访问冲突,而且没有了之前jameshooo提到的跨线程问题,所以代码能够正常运行了。
不过目前还只是猜想而已,未验证。
呵呵,自己先恭喜下自己,虽然原因还不清楚,但是代码终于可以跑了,哦吼吼~
回复
a220315410 2010-07-22
路过顶下~
回复
nmg1852951 2010-07-22
明白了,我再查下资料
回复
jameshooo 2010-07-21
先啃啃书吧,概念性的东西必须有个初步印象,一时半会儿难解释清楚
回复
nmg1852951 2010-07-21
[Quote=引用 4 楼 jameshooo 的回复:]
接口指针未列集,而你是在另一个线程中调用的,导致这个错误的发生。

微软在这里摆了几个陷阱,就等着痴人跳入火坑不能自拔:
陷阱1:WM_HTML_GETOBJECT消息从来都不是为跨进程跨线程准备的。
陷阱2:WM_HTML_GETOBJECT消息的返回结果是灰常灰常不安全的,因为它就是一个IUnknown*。不要迷信ObjectFromLresult,它不会帮你任何忙,仅仅代替你执行了一……
[/Quote]
能介绍的具体点么,本人刚离开学校,参加工作,新学MFC,对于window的编程,不是很熟悉。
至于
spDoc->get_Script( &spDisp );
spWin = spDisp;
spWin->get_document( &pDoc2 );
这个三行按照我的理解,应该是去获取Script engine中去获取script对象,再从script对象中去获取automation object,至于为什么要这么做,我自己也不是很清楚,从网上下载的demo中有这么写,我就这么用了,惭愧~
回复
nmg1852951 2010-07-21
[Quote=引用 3 楼 skyxie 的回复:]
你调用 GetDocInterface 的时机不对, 请确保在调用该函数的时候web页面的已加载完成。

具体点,你的hook是在啥时候被调用的?
[/Quote]
Hook是在鼠标的左键按下的时候触发的,我可以保证在我进行鼠标操作的时候,页面已经加载完成。
PS:其实我猜想过这个原因,所以有试过在获取接口不成功的时候,在
hr=(*pfObjectFromLresult)( lRes, IID_IHTMLDocument, 0, (void**)&spDoc );
语句上写了个while循环,当它无法取到接口,就不停的取,结果这个while变成了死循环,把我电脑都卡死了饿,悲剧
回复
jameshooo 2010-07-20
接口指针未列集,而你是在另一个线程中调用的,导致这个错误的发生。

微软在这里摆了几个陷阱,就等着痴人跳入火坑不能自拔:
陷阱1:WM_HTML_GETOBJECT消息从来都不是为跨进程跨线程准备的。
陷阱2:WM_HTML_GETOBJECT消息的返回结果是灰常灰常不安全的,因为它就是一个IUnknown*。不要迷信ObjectFromLresult,它不会帮你任何忙,仅仅代替你执行了一个IUnknown::QueryInterface而已。
陷阱3:就算你获取到了IHTMLDocument2,可能也只是一个不受信任的接口指针,后续访问还会遇到权限问题。

还有,楼主的几句代码我没看懂:
spDoc->get_Script( &spDisp );
spWin = spDisp;
spWin->get_document( &pDoc2 );
不知道在干什么
回复
skyxie 2010-07-20
你调用 GetDocInterface 的时机不对, 请确保在调用该函数的时候web页面的已加载完成。

具体点,你的hook是在啥时候被调用的?
回复
nmg1852951 2010-07-20
无奈的再顶下自己,别沉下去了
回复
nmg1852951 2010-07-20
自己顶下自己,希望哪位大大快来回答下~
回复
发动态
发帖子
HTML/XML
创建于2007-09-28

3053

社区成员

VC/MFC HTML/XML
申请成为版主
社区公告
暂无公告