BHO(Browser Helper Object,浏览器辅助对象,简称BHO)。BHO是微软推出的作为浏览器对第三方程序员开放交互接口的业界标准,通过简单的代码就可以进入浏览器领域的“交互接口”(INTERACTIVED Interface)。通过这个接口,程序员可以编写代码获取浏览器的行为,比如“后退”、“前进”、“当前页面”等,利用BHO的交互特性,程序员还可以用代码控制浏览器行为,比如修改替换浏览器工具栏,添加自己的程序按钮等。这些在系统看来都是没有问题的。BHO原来的目的是为了更好的帮助程序员打造个性化浏览器,以及为程序提供更简洁的交互功能,现在很多IE个性化工具就是利用BHO的来实现。
在正式利用VC++编写代码之前,我们需要了解一些东西,首先是IE浏览器加载BHO插件的原理。
1.IE的窗口打开时,先寻找HKLM下的SOFTWA RE\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects\里的CLSID,这些CLSID,都对应着相应的BHO插件,然后根据这个CLSID到HKCR下的CLSIDs里找到此插件的信息,包括文件位置等。
2.IE根据找到的CLSID信息创建BHO对象,并且查找IObjectWithSite接口。(这个接口非常简单,只有SetSite和GetSite两个方法)
3.IE把IWebBrowser2(浏览器插件)传到BHO的SetSite方法,用户在此方法中可挂载自己的事件处理方法。
4.窗口关闭时,iE把null传到BHO的SetSite方法,此方法用来去掉挂载的事件处理方法。
了解了IE浏览器加载BHO的方法之后,我们就来看一下BHO插件的编写流程。
1、创建IObj ectWithSite显式接口,创建COM类型,实现继承IObjectWithSite接口
2、实现此接口并在SetSite方法里加上所要挂载的事件
3、处理事件
4、注册此BHO到注册表中HKLM下的Softw are\\Microsoft\\Windows\\CurrentVersion\\ExplorerBrowser Helper Objects;(HKCR下的CLSIDs是根据上面的路径自动注册的)
5、.net下须设置此BHO项目的”配置属性一>生成”中为Interop注册为True,这样才能将.net类库文件注册到COM。
我们采用VC6.O创建好环境之后,就要进行代码的编写了。由于我们在IE浏览器中加载插件,所以其他的浏览器我们就不允许dll加载了。这样我们就需要在dllMain函数中对加载该dll的程序进行判断,代码如下:
STDMETHODIMP CIEH1probj::lnvoke(DISPID dispidMemberm,REFIID riid,LCID lcid,WORD wFlags,
DISPPARAMS*pDispParams,VARIANT*pvarResult,
EXCEPINFO* pExceplnfo,UINT*puArgerr)
{
USES_CONVERSION;
if (!pDispParams)
return E_INVALIDARG;
LPOLESTR lpURL=NULL;
m_spwebBrowser2->get_LocationURL(&lpURL);
char sitelist{100}{1024}; //所有站点名称(1024)
char site{1024}; //站点名称
ifstream in("C:\\SiteList dat",ios::in);//从我们的文件中读取要检测的网址
if(in.fail())
{
return E_INVALIDARG;
}
这段代码我们添加在dllMain函数的开始位置,这样就能确保只有iexplore.exe才能加载我们的插件。BHO对象与浏览器进行交互是通过事件实现的,那么他们之间的交互有几种事件呢?下面就列举一下常用到的事件:
DISPID__ BEFORENAVIGATE2: 该事件在浏览器准备下载网页之前触发,这样这个事件就可以用在我们检测用户输入的网页地址上。
DISPID_DOWNLOADBEGrN:该事件在浏览器开始下载网页时触发。
DISPID_NAVIGATECOMPLETE:该事件是在一个链接(网页窗口或者网页Frame框架窗口)被完全打开后,IE浏览器或WebBrowser控件触发的事件。这个事件已经废弃。应该使用DISPIDNAVIGATECOMPLETE2。
DISPID_DOVVrNLOADCOMPLETE:该事件在网页完全被浏览器下载完毕之后触发。
DISPID_DOCUMENTCOMPLETE:页面加载完毕时触发该事件,当每个FRAME加载完毕后都会触发DISPID_DOCUMENTCOMPLETE。可以在DISPID_DOCUMENTCOMPLETE中,判断是否是整个页面加载完毕。
DISPID_NEWWINDOW2:该事件在有新的窗口打开时触发,例如弹窗网页。
了解了上述的事件机制之后,我们就明确怎么编写我们的代码了,既然是监控网址的,那么我们可以在DISPID_BEFORENAVIGATE2事件中对网址进行监控。事件的方法我们需要在Invoke函数中编写。这里我们用switch语句对事件进行判断,要处理的网址我们放到文件里,让程序从文件里读取网址,然后与用户输入的网址进行对比。
编译之后生成了一个dll文件,这就是我们需要的文件。我们在网址文件中写入我们需要拦截的网址,这里用百度做测试。下一步就是注册我们的dll文件,用cmd命令“regsvr32 c://IEHelper.dll”来注册,注册结果,注册成功。我们打开一个新的网页,输入网址百度回车,弹出了我们的显示信息,ok,到这里我们的目的就完成了,当然读者可以通过修改上述代码进行二次开发,可以实现网址替换、网页内容替换等等功能,这些有待读者自己挖掘。