实用代码:【源码下载】类:CVBWebBrowserHunter —— 通过指定Shell Embedding类窗口句柄获得浏览器对象
【源码下载地址】:http://60.191.21.235:1122/vbwebbrowserhunter.rar
关于如何取得浏览器接口的问题大家已经关注很久了,特别是VBAHZ同志,时不时地就贴个帖子出来,呵呵……为了不辜负VBAHZ同志对本人的抬举,偶便决定看看这个有点麻烦的问题……
要从指定窗口返回浏览器对象需要解决这么两个问题:
1、得到浏览器对象接口
2、跨进程调用对象
这两个问题用VB实现起来都不是什么轻松的事情。因为涉及到接口编程,所以可能需要用到自定义的类型库,麻烦!跨进程调用COM对象需要进行列集(Marshal)和散集(Unmarshal),更是麻烦!麻烦!不过麻烦归麻烦,问题还是要一个一个解决的。
首先,我们来看看如何得到浏览器对象接口。在翻遍了msdn后,最后终于在一个角落里发现了秘诀。其大致是这样描述整个过程的:
1、 发送一个微软没有公布的消息WM_USER+7到指定窗口,获得一个IShellView指针
2、 从这个指针用QueryInterface获得一个IServiceProvider接口
3、 从IServiceProvider接口的QueryService方法得到一个服务ID为SID_STopLevelBrowser的IServiceProvider接口
4、 最后从服务ID为SID_STopLevelBrowser的IServiceProvider接口调用QueryService方法得到IID_IWebBrowser2接口
以上这个过程用VC实现起来是非常快的,而用VB的话就头疼了。另外,这些方法需要在指定窗口所在的线程里运行才可以,否则,后果将不可预料……
而第二个问题涉及到COM对象的列集(Marshal)和散集(Unmarshal)。很明显,列集的工作肯定也要在目标窗口所在线程中完成,而散集的工作则要在本地程序里来做。
因此,综上所述,要解决上述问题,就必须要在目标窗口线程空间里插入代码。
代码插入有多种方法,我这次还是跟以往一样用的是直接代码写入,但跟以往有一点不同的是,这次的代码插入后要立即运行。我先想到了CreateRemoteThread,但是后来再想,用这个API创建的是一个新的线程,从这个线程访问另一个线程中的对象,同样需要进行列集和散集的操作,而这样实在太麻烦了。而后我想到了在窗体过程(WindowProc)上安装个钩子,然后马上个发送NULL消息来激活代码,但是,WindowProc是个使用比较频繁的过程,弄不好的话就会把对象窗口弄疯掉,而且,同样的,这样做麻烦阿~~最后,我想到了SetThreadContext,使用这个api我们就可以设定目标线程的eip,hoho,没错,就是他了~~