到底什么是浏览器到底哪个好帮助程序对象

1&&/&&1&&页
跳转 0 ? parseInt(this.value) : 1) + '.aspx';}else{window.location='showtopic.aspx?topicid=8123332&page=' + (parseInt(this.value) > 0 ? parseInt(this.value) : 1) ;}}"" size="4" maxlength="9"
class="colorblue2"/>页
【求助】我的电脑IE里有一个浏览器帮助程序对象(BHO)删不掉!!!!!!!
初生襁褓狮
【求助】我的电脑IE里有一个浏览器帮助程序对象(BHO)删不掉!!!!!!!
我的电脑IE里面有一个有一个浏览器帮助程序对象(BHO)怎么也删不掉,我进过安全模式删过,但是没有效过,我也修改过注册表,但是还没有效果,求高手帮帮忙!!!!路径是C:\WINNT\system32\mljji.dll帮帮忙了QQ:
下载次数:172
文件类型:application/octet-stream
上传时间: 8:38:48
初生襁褓狮
总共抓了两张图片
下载次数:156
文件类型:application/octet-stream
上传时间: 8:40:18
初生襁褓狮
自己顶一下高手们帮帮忙
初生襁褓狮
帮帮忙呀!我用别的工具也不可以,怎么可以清除呀!
自信弱冠狮
用Hijackthis试试
特邀体验者
来自:0GiNr
去pjf.blogone.net,下载IceSword1.18,运行后展开"注册表",找到:hkey_local_machine\software\microsoft\windows\currentversion\explorer\browser object helper删除其下指到你说的那个DLL项PS:如果删除不了,多试几次WINDOWS的注册表编辑器regedit无法删除这个.
威望:11197
1&&/&&1&&页
跳转 0 ? parseInt(this.value) : 1) + '.aspx';}else{window.location='showtopic.aspx?topicid=8123332&page=' + (parseInt(this.value) > 0 ? parseInt(this.value) : 1) ;}}"" size="4" maxlength="9"
class="colorblue2"/>页
论坛跳转...
热点专题 &&瑞星杀毒软件 && &&瑞星杀毒软件V16+ && && &&V16+新引擎测试专区 && &&瑞星全功能安全软件 && &&瑞星杀毒软件2011 &&瑞星安全联盟论坛 &&瑞星安全随身WiFi &&瑞星个人防火墙V16 && &&广告过滤 && &&瑞星个人防火墙2011 &&瑞星路由安全卫士 && &&路由系统内核漏洞 &&瑞星积分商城 && &&北方区 && &&华东区 && &&华南区 && &&木马入侵拦截有奖体验专区 && &&瑞星2009版查杀引擎测试 && &&瑞星2009测试版问题反馈 && && &&瑞星杀毒软件2009公测 && && &&瑞星个人防火墙2009公测 && && &&瑞星全功能安全软件2009公测瑞星产品求助区 &&企业级安全产品 && &&瑞星企业终端安全管理系统 && &&瑞星安全云终端 &&瑞星手机安全助手 &&APP保镖 &&瑞星安全浏览器 &&瑞星其他产品 && &&瑞星安全助手 && && &&卡卡上网安全助手 && &&瑞星WiFi助手 && &&瑞星软件管家 && &&瑞星加密盘 && &&账号保险柜5.0 && &&瑞星专业数据恢复技术交流区 &&反病毒/反流氓软件论坛 && &&菜鸟学堂 && &&安全技术讨论 &&可疑文件交流 &&恶意网站交流 && &&瑞星云安全网站联盟专版 && &&每日网马播报 &&入侵防御(HIPS) &&系统软件 && &&防火墙自定义规则 &&硬件交流综合娱乐区 &&Rising茶馆 &&影音贴图 &&瑞星安全游戏 && &&凡人修真 && &&华人德州扑克 && &&一球成名 && &&星际世界 && &&神仙道 && &&赢家竞技 && &&梦幻飞仙 && &&三国演义 && &&仙落凡尘 && &&秦美人 && &&攻城掠地 && &&女神联盟 && &&风云无双 && &&傲视九重天 && &&深渊 && &&魅影传说 && &&热血屠龙 && &&雷霆之怒 && &&大天使之剑 && &&传奇霸业 && &&无上神兵 &&活动专区 && &&实习生专区 && && &&实习生交流区 && && && &&实习生签到区 && && &&实习生考核区 && &&“安全之狮”校园行活动专版 && &&历史活动 && && &&论坛9周年活动专区 && && &&关注灾情 同心抗灾本站站务区 &&站务 &&版主之家[限] && &&禁言禁访记录 &&待审核 &&瑞星客户俱乐部[限]转载,原文;
这篇文章是应同学们的要求写的,以前都是用VC++ 6.0+Platform SDK完成的. 迁移到 VS2008之后,原来Visual Studio 6.0里的BHO向导不复存在,因此特此不厌其烦,详细说明,本文也适用于VS2005.
首先谈BHO的开发工具,我偏向使用VC++(unmanaged C++) 作为开发工具,因为Java JVM或.Net CLR的虚拟机是个很笨重的东西,也是内存杀手, 并不具备写plugin的快捷轻巧的特点.个人并不喜欢将其作为Plug-in的开发平台,不过我会有另文说明用C#开发BHO的全过程, 作为那些偏重开发效率的同学的参考.
其次是类库的选择,我倾向利用“活动模板库”(ATL) 来开发使用 C++ 的 BHO。之所以使用 ATL,是因为它方便地实现了我们可以按需进行扩展的基本样板。尽管使用“Microsoft 基础类”(MFC) 或 Win32 API 和 COM)也可以创建BHO,但 ATL 是为我们提供了自动处理许多细节的轻型库,包括建立含有 BHO 类标识符 (CLSID) 的注册表。
ATL 的另一个优势在于它的 COM智能感知指针类(例如,CComPtr 和 CComBSTR),这些类可管理 COM 对象的生命周期。例如,CComPtr 在赋值时会调用 AddRef,而在对象被销毁或超出范围时会调用 Release。智能指针简化了代码并且有助于避免内存泄漏。当在单个方法范围内使用时,它们的稳定性和可靠性尤为有用。
介绍完ATL, 我们也简单介绍一下BHO. BHO是将自定义功能添加到 Internet Explorer 的轻型 DLL 扩展,除了IE, BHO 还可以将功能添加到 Windows 资源管理器外壳程序.
BHO 通常并不提供其自身的任何用户界面 (UI)。它们而是通过在后台响应浏览器事件和用户输入数据来发挥作用。例如,BHO 可以拦截弹出窗口、自动填充窗体或为鼠标手势添加支持。
有一种常见误解认为工具栏扩展项需要 BHO.但如果将 BHO 与工具栏配合使用,则可以实现更丰富的用户体验。(关于IE工具栏的编程,在另一篇文章中说明).
BHO 的生命周期与它所交互的浏览器实例的生命周期相等。在 IE 6 和早期版本中,这意味着要为每个新的顶层窗口创建(和销毁)一个新 BHO。在IE 7中则是为每个选项卡都创建和销毁一个新 BHO。
BHO 必须实现 IObjectWithSite 接口, 该接口提供了两个方法GetSite和SetSite。根据MSDN的说明:
GetSite: Gets the last site set with IObjectWithSite::SetSite. If there is no known site, the object returns a failure code.
SetSite: Provides the site's IUnknown pointer to the object.
Gets the last site set with IObjectWithSite::SetSite. If there is no known site, the object returns a failure code.
Provides the site's IUnknown pointer to the object.
我们主要是对后者进行调用,此方法方便了与 Internet Explorer 的初始通信,并会在其将要释放时通知 BHO。我们实现此接口,然后将 BHO 的 CLSID 添加到注册表中,就可以创建一个简单的浏览器扩展。过程如下:
1. 在Visual Studio中,选择VC++中的ATL项目, 创建一个新的项目MySolutionPlugin, 在随后的向导中,确认Server Type是Dll, Visual Studio会为我们创建程序的模板.
2. 为该项目添加我们的程序主体, (不熟悉visual studio的同学在资源浏览器里的右键菜单里选 add--&class, 可别选到New Item), 类型选ATL Simple Object , short name命名为RayBHO,各项属性如下:
a) “线程模型” ---“Apartment”
b) “聚合”---“否”
c) “接口”---“双重”
d) “支持”---勾上“IobjectWithSite”。
具体的含义请参考MSDN.
一般来说,Internet Explorer 至少调用SetSite方法两次: 一次用于建立连接,另一次则是在浏览器退出时。我们 BHO 中的 SetSite 实现将执行以下操作:
  o存储对站点的引用。在初始化期间,浏览器将 IUnknown 指针传递给顶层 WebBrowser 控件,然后 BHO 将对它的引用存储在一个专用成员变量中。
  o释放目前被占用的站点指针。Internet Explorer 传递 NULL 时,BHO 必须释放所有接口引用并且断开与浏览器的连接。
要实现SetSite,我们需手工在添加一个public的方法:
STDMETHOD(SetSite)(IUnknown * pUnkSite);
STDMETHOD(SetSite)(IUnknown * pUnkSite);
STDMETHOD 宏是将方法标记为虚方法并且确保其具有适用于公共 COM 接口的调用约定的一个ATL 约定, 它有助于区分 COM 接口和该类中可能存在的其他公共方法。其实现成员方法时应相应使用 STDMETHODIMP 宏。同时我们需要声明一个私有变量来保存Browser的指针&
CComPtr&IWebBrowser2& m_spWebB
CComPtr&IWebBrowser2& m_spWebB//保存Browser指针的私有变量
然后是SetSite的实现
STDMETHODIMP CRayBHO::SetSite(IUnknown*pUnkSite) { if(pUnkSite!=NULL) { pUnkSite-&QueryInterface(IID_IWebBrowser2,(void**)&m_spWebBrowser);
} else { m_spWebBrowser.Release(); } return IObjectWithSiteImpl::SetSite(pUnkSite);
STDMETHODIMP CRayBHO::SetSite(IUnknown*pUnkSite)
if(pUnkSite!=NULL)
//缓存指向IWebBrowser2的指针。
pUnkSite-&QueryInterface(IID_IWebBrowser2,(void**)&m_spWebBrowser);
//在此释放缓存的指针和其他资源。
m_spWebBrowser.Release();
//返回基类实现
return IObjectWithSiteImpl::SetSite(pUnkSite);
从上面的介绍我们知道, 初始化期间,浏览器将传递一个对其顶层 IWebBrowser2 接口(我们对其进行缓存处理)的引用。浏览器关闭时将传递 NULL,为避免内存泄漏和循环引用计数,此时释放所有指针和资源非常重要。最后,我们调用基类实现以便继续执行接口合约的其余部分。
加载DLL 后,系统将通过 DLL_PROCESS_ATTACH 通知调用 DllMain 函数。由于 Internet Explorer 大量使用多线程,因此,对 DllMain 的频繁的 DLL_THREAD_ATTACH 和 DLL_THREAD_DETACH 通知会降低扩展和浏览器进程的整体性能。
如果BHO 不需要线程级的跟踪,我们可以在 DLL_PROCESS_ATTACH 通知期间调用 DisableThreadLibraryCalls 以避免新线程通知的额外开销。修改DllMain.cpp 中的DllMain函数:
extern &C& BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{ if(dwReason==DLL_PROCESS_ATTACH)
{ DisableThreadLibraryCalls(hInstance); } return _AtlModule.DllMain(dwReason,lpReserved);
extern &C& BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
if(dwReason==DLL_PROCESS_ATTACH)
DisableThreadLibraryCalls(hInstance);
return _AtlModule.DllMain(dwReason,lpReserved);
要使BHO工作,我们还需要把BHO 的 CLSID 添加到注册表中。此条目会将 此DLL 标记为浏览器帮助程序对象,并使 Internet Explorer 在启动时加载 BHO。我们可以在MySolutionPlugin.idl中找到该BHO的CLSID.幸运的,Visual Studio会帮助我们实现这些, 你看到:
importlib(&stdole2.tlb&);
[ uuid(057F3E68-6C2E-40A5-A641-E8CF9D6766F3), helpstring(&RayBHO Class&)
importlib(&stdole2.tlb&);
uuid(057F3E68-6C2E-40A5-A641-E8CF9D6766F3),
helpstring(&RayBHO Class&)
您的机器的CLSID可能有所不同, 接着打开RayBHO.rgs文件,添加入:
HKLM { NoRemove SOFTWARE { NoRemove Microsoft { NoRemove Windows { NoRemove CurrentVersion { NoRemove Explorer { NoRemove 'Browser Helper Objects'
{ ForceRemove {057F3E68-6C2E-40A5-A641-E8CF9D6766F3} = s 'RayBHO Class'
{ val NoExplorer = d '1'
} } } } } } } }
NoRemove SOFTWARE
NoRemove Microsoft
NoRemove Windows
NoRemove CurrentVersion
NoRemove Explorer
NoRemove 'Browser Helper Objects'
ForceRemove {057F3E68-6C2E-40A5-A641-E8CF9D6766F3} = s 'RayBHO Class'
val NoExplorer = d '1'
这一段是为了在注册表里添加一个双字节的NoExplorer=1的键,不让Windows Explorer加载该BHO,因此该BHO只能在ie中运行.
你可以编译这个BHO. 如果一切正常, 你可以在IE的管理加载项里看到这个BHO.
如果不幸报错: 该BHO无法被注册,根据我的经验,原因大概有2类,可以依次检查
1. 你是否有管理员权限以修改注册表,如不是管理员身份,可以在菜单上右击Microsoft Visual studio 2008,从右键菜单中选择&运行方式&...
2. 你的注册表条目语法是否正确,或者含有非法字符.
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:15730次
排名:千里之外
转载:11篇
(1)(3)(2)(2)(1)(4)笔试题_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
上传于||暂无简介
阅读已结束,如果下载本文需要使用0下载券
想免费下载更多文档?
定制HR最喜欢的简历
下载文档到电脑,查找使用更方便
还剩33页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢1605人阅读
摘要:本文说明了如何使用 Microsoft Visual Studio 2005 创建一个简单的&浏览器帮助程序对象&(BHO),即实现 IObjectWithSite 接口并将其自身附加到 Internet Explorer 的一种&组件对象模型&(COM) 对象。本文逐步说明了如何创建入门级 BHO。首先,BHO 会在 Internet Explorer 加载文档时显示消息&大家好!&。然后,BHO 被扩展为从已加载页面删除图像。本文面向的是想要了解如何扩展浏览器功能以及如何为 Internet Explorer 创建 Web 开发人员工具的开发人员(本文还包含指向英文网页的链接)。
本文凭借 Microsoft Visual Studio 2005 和&活动模板库&(ATL) 来开发使用 C++ 的 BHO。我们之所以决定使用 ATL,是因为它方便地实现了我们可以按需进行扩展的基本样板。还有其他方法可供用于创建 BHO(例如,使用&Microsoft 基础类&(MFC) 或 Win32 API 和 COM),但 ATL 是为我们自动处理许多细节的轻型库,包括建立含有 BHO 类标识符 (CLSID) 的注册表。
ATL 的另一个优势在于它的 COM 感知智能指针类(例如, 和 ),这些类可管理 COM 对象的生命周期。例如,CComPtr 在赋值时会调用 AddRef,而在对象被销毁或超出范围时会调用 Release。智能指针简化了代码并且有助于避免内存泄漏。当在单个方法范围内使用时,它们的稳定性和可靠性尤为有用。
本文的第一部分向您逐步介绍了如何实现简单的 BHO 并验证它是否由 Internet Explorer 加载。接下来的部分将说明如何将 BHO 连接到浏览器事件,最后一部分将介绍与更改网页外观的 DHTML 文档对象模型 (DOM) 的简单交互。
到底什么是浏览器帮助程序对象 (BHO)?简言之,BHO 是将自定义功能添加到 Internet Explorer 的轻型 DLL 扩展。BHO 还可以将功能添加到 Windows 资源管理器外壳程序(尽管这并不常见,也不是本文重点)。
BHO 通常并不提供其自身的任何用户界面 (UI)。它们而是通过在后台响应浏览器事件和用户输入数据来发挥作用。例如,BHO 可以、自动填充窗体或为添加支持。有一种常见误解认为需要 BHO;但如果将 BHO 与工具栏配合使用,则可以实现更丰富的用户体验。
注意 BHO 对于最终用户和开发人员同样都是便捷的工具;但由于 BHO 被赋予了对浏览器和 Web 内容的相当大的控制能力,并且它们通常都处于未检测的状态,因此用户应十分谨慎地从可靠来源获取和安装 BHO。
BHO 的生命周期与它所交互的浏览器实例的生命周期相等。在 Internet Explorer 6 和早期版本中,这意味着为每个新的顶层窗口都创建(和销毁)一个新 BHO。另一方面,Internet Explorer 7 会为每个选项卡都创建和销毁一个新 BHO。BHO 不是由承载 的其他应用程序加载,也不是由 HTML 对话框之类的窗口加载。
BHO 的主要要求是实现
接口。此接口提供了一个方法(即 SetSite),此方法方便了与 Internet Explorer 的初始通信,并会在其将要释放时通知 BHO。我们实现此接口,然后将 BHO 的 CLSID 添加到注册表中,由此创建一个简单的浏览器扩展。
让我们开始吧。
通过 Microsoft Visual Studio 2005 创建 BHO 项目:
在&文件&菜单上,单击&新建项目...&。
随即出现&新建项目&对话框。此对话框将列出 Visual Studio 可以创建的应用程序类型。
在 Visual C++ 节点下,选中&ATL&(如果它未被选中),然后从 Visual C++ 项目类型中选择&ATL 项目&。将项目命名为&HelloWorld&并使用默认位置。单击&确定&。
在&ATL 项目向导&中,确保服务器类型为&动态链接库 (DLL)&,然后单击&完成&。
此时,Visual Studio 已为 DLL 创建了样板。现在,我们将添加实现 BHO 的 COM 对象。
在&解决方案资源管理器&面板上,右键单击该项目,然后从&添加&子菜单中选择&类...&。
选中&ATL 简单对象&,然后单击&添加&。
随即出现&ATL 简单对象向导&。
在&ATL 简单对象向导&的&名称&中,键入&HelloWorldBHO&以作为&短名称&。
余下的名称将自动填充。
在&ATL 简单对象向导&的&选项&中,选中&线程模型&下的&Apartment&、&聚合&下的&否&、&接口&下的&双重&以及&支持&下的&IobjectWithSite&。
单击&完成&。
以下文件将作为此项目的一部分创建。
HelloWorldBHO.h & 此头文件包含 BHO 的类定义。
HelloWorldBHO.cpp & 此源文件是项目的主文件并且包含 COM 对象。
HelloWorld.cpp & 此源文件用于实现通过 DLL 提供 COM 对象的导出。
HelloWorld.idl & 此源文件可用于定义自定义 COM 接口。对于本文,我们将不更改此文件。
HelloWorld.rgs & 此资源文件包含注册和取消注册 DLL 时编写和删除的注册表项。
实现基本要素
&ATL 项目向导&提供了 SetSite 的默认实现。尽管 IObjectWithSite 的接口合约暗示了此方法可以在必要时被反复调用,但确切来说,Internet Explorer 只调用此方法两次;一次用于建立连接,另一次则是在浏览器退出时。特别要提的是,我们 BHO 中的 SetSite 实现将执行以下操作:
存储对站点的引用。在初始化期间,浏览器将 IUnknown 指针传递给顶层 WebBrowser 控件,然后 BHO 将对它的引用存储在一个专用成员变量中。
释放目前被占用的站点指针。Internet Explorer 传递 NULL 时,BHO 必须释放所有接口引用并且断开与浏览器的连接。
在处理 SetSite 的过程中,BHO 将根据需要执行其他初始化和非初始化。例如,您可以建立与浏览器的连接点以便接收浏览器事件。
HelloWorldBHO.h
在 Visual Studio 的&解决方案资源管理器&中双击打开 HelloWorldBHO.h。
首先,包含 shlguid.h。此文件定义了
的接口标识符和稍后在项目中使用的事件。
#include &shlguid.h&
// IID_IWebBrowser2、DIID_DWebBrowserEvents2 等。
接下来,在 CHelloWorldBHO 类的公共部分声明 SetSite。
STDMETHOD(SetSite)(IUnknown *pUnkSite);
STDMETHOD 宏是一个将方法标记为虚拟方法并且确保其具有适用于公共 COM 接口的调用约定的 ATL 约定。它有助于区分 COM 接口和该类中可能存在的其他公共方法。实现成员方法时同样也会使用 STDMETHODIMP 宏。
最后,在类声明的专用部分中声明某成员变量以存储浏览器站点。
CComPtr&IWebBrowser2&
HelloWorldBHO.cpp
现在,切换到 HelloWorldBHO.cpp 并为 SetSite 插入以下代码。
STDMETHODIMP CHelloWorldBHO::SetSite(IUnknown* pUnkSite) {
if (pUnkSite != NULL)
// 缓存指向 IWebBrowser2 的指针。
pUnkSite-&QueryInterface(IID_IWebBrowser2, (void**)&m_spWebBrowser);
// 在此释放缓存的指针和其他资源。
m_spWebBrowser.Release();
// 返回基类实现
return IObjectWithSiteImpl&CHelloWorldBHO&::SetSite(pUnkSite); }
初始化期间,浏览器将传递一个对其顶层 IWebBrowser2 接口(我们对其进行缓存处理)的引用。非初始化期间,浏览器将传递 NULL。为避免内存泄漏和循环引用计数,此时释放所有指针和资源非常重要。最后,我们调用基类实现以便它可以履行接口合约的其余部分。
HelloWorld.cpp
加载 DLL 后,系统将通过 DLL_PROCESS_ATTACH 通知调用 DllMain 函数。由于 Internet Explorer 大量使用多线程,因此,对 DllMain 的频繁的 DLL_THREAD_ATTACH 和 DLL_THREAD_DETACH 通知会降低扩展和浏览器进程的整体性能。既然该 BHO 不需要线程级的跟踪,我们可以在 DLL_PROCESS_ATTACH 通知期间调用
以避免新线程通知的额外开销。
在 HelloWorld.cpp 中,如下编写 DllMain 函数的代码:
extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) {
if (dwReason == DLL_PROCESS_ATTACH)
DisableThreadLibraryCalls(hInstance);
return _AtlModule.DllMain(dwReason, lpReserved);
剩下要做的只是将 BHO 的 CLSID 添加到注册表中。此条目会将 DLL 标记为浏览器帮助程序对象,并使 Internet Explorer 在启动时加载 BHO。Visual Studio 可在生成项目时注册 CLSID。
注意 在 Windows Vista 上,Visual Studio 需要提升的特权才能与注册表进行交互。请确保通过在&开始&菜单中右键单击 Microsoft Visual Studio 2005 并选择&以管理员身份运行&来启动开发环境。
此 BHO 的 CLSID 可在 HelloWorld.idl 中找到(位于如下所示的代码块中):
importlib("stdole2.tlb");
uuid(D2F7E1E3-C9DC-4349-B72C-D5A708D6DD77),
helpstring("HelloWorldBHO Class")
请注意,此文件包含三个 GUID;我们需要的是用于类的 CLSID,而不是用于库的 CLSID 或接口 ID。
创建自行注册的 BHO:
从 Visual Studio 中的&解决方案资源管理器&打开 HelloWorld.rgs。
将以下代码添加到文件末尾:
NoRemove SOFTWARE {
NoRemove Microsoft {
NoRemove Windows {
NoRemove CurrentVersion {
NoRemove Explorer {
NoRemove '浏览器帮助程序对象' {
ForceRemove '{D2F7E1E3-C9DC-4349-B72C-D5A708D6DD77}' = s 'HelloWorldBHO' {
val 'NoExplorer' = d '1'
将上述 ForceRemove 后面的 GUID 替换为 BHO 的 CLSID(可在 HelloWorld.idl 中找到)。
切勿替换大括号。
保存文件,然后重新生成解决方案。(按 F6。)
Visual Studio 将自动注册该对象。
NoRemove 关键字表示取消注册 BHO 时将不删除该注册表项。除非您指定了此关键字,否则将删除空的注册表项。ForceRemove 关键字表示将删除该注册表项以及它所包含的任何值和子项。ForceRemove 还将导致在注册 BHO 后重新创建该注册表项(如果它已存在)。
既然此 BHO 专用于 Internet Explorer,那么我们指定 NoExplorer 值以防止 Windows Explorer 加载它。值和类型是什么都不重要,只要 NoExplorer 条目存在,Windows Explorer 就不会加载 BHO。
现在,您就可以从 Visual Studio 2005 中的&生成&菜单生成解决方案。
为了进行快速测试,请在 SetSite 中设置一个断点,然后按 F5 启动调试程序。当出现&调试会话的可执行文件&对话框时,选择&默认的 Web 浏览器&,然后单击&确定&。如果 Internet Explorer 不是您的默认浏览器,则可以浏览查找可执行文件。
注意 在 Windows Vista 上,Internet Explorer 的&保护模式&功能将启动另一个进程,然后退出,这样会给调试带来一点难度。您可以通过以下两种方式轻松关闭当前会话的&保护模式&:从管理进程(例如 Visual Studio)启动浏览器,或者创建一个本地 HTML 文件并将其指定为 Internet Explorer 的命令行参数。
浏览器启动时,将加载 BHO 的 DLL。命中断点时,请注意是否设置了 pUnkSite 参数。再次按 F5 以继续加载主页。
关闭浏览器以验证是否通过 NULL 再次调用了 SetSite。
对事件做出响应
既然已经确认了 Internet Explorer 可以加载和运行 BHO,那就让我们在所举示例的基础上再深入一些,将 BHO 扩展到响应浏览器事件。在本部分中,我们介绍如何使用 ATL 为 (在页面加载后显示一个消息框)实现一个事件处理程序。
为接到事件通知,BHO 建立一个与浏览器之间的连接点;为响应这些事件,它将实现 。根据 DocumentComplete 的文档,该事件有两个参数:pDisp(IDispatch 的指针)和 pUrl。这些参数将作为事件的一部分传递给 IDispatch::Invoke;但手动析取这些事件参数并非一项简单的任务,并且易于出错。幸好 ATL 提供了一个默认实现,可以帮助简化这个事件处理逻辑。
HelloWorldBHO.h
首先通过包含 exdispid.h(为浏览器事件定义调度 ID)处理 HelloWorldBHO.h。
#include &exdispid.h& // DISPID_DOCUMENTCOMPLETE 等。
接下来,从 IDispEventImpl 基类进行派生,该基类为处理事件提供了除 Invoke 之外的另一个简单安全的替代方法。IDispEventImpl 与事件汇映射配合工作,以将事件路由到相应的处理程序函数。我们明确说明,想要使用以下类定义(突出显示)处理由 DWebBrowserEvents2 接口定义的事件。
class ATL_NO_VTABLE CHelloWorldBHO :
public CComObjectRootEx&CComSingleThreadModel&,
public CComCoClass&CHelloWorldBHO, &CLSID_HelloWorldBHO&,
public IObjectWithSiteImpl&CHelloWorldBHO&,
public IDispatchImpl&IHelloWorldBHO, &IID_IHelloWorldBHO, &LIBID_TestBho1Lib, /*wMajor =*/ 1, /*wMinor =*/ 0&,
public IDispEventImpl&1, CHelloWorldBHO, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 1&
接下来,添加将事件路由到新的 OnDocumentComplete 事件处理程序方法的 ATL 宏,该事件处理程序方法采用的是 DocumentComplete 事件所定义的相同参数和顺序。将以下代码放置到该类的公共部分。
BEGIN_SINK_MAP(CHelloWorldBHO)
SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete) END_SINK_MAP()
// DWebBrowserEvents2
void STDMETHODCALLTYPE OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL);
提供给 SINK_ENTRY_EX 宏 (1) 的数字指的是 IDispEventImpl 类定义的第一个参数,在必要时用于区分来自不同接口的事件。另请注意,不能从该事件处理程序返回值;这是因为 Internet Explorer 无论怎样都会忽略从 Invoke 返回的值。
最后,添加一个专用成员变量,以跟踪各对象是否已建立了与浏览器的连接。
HelloWorldBHO.cpp
要通过事件映射将事件处理程序连接到浏览器,可在处理 SetSite 期间调用 DispEventAdvise。同样,使用 DispEventUnadvise 断开连接。
以下是 SetSite 的新实现:
STDMETHODIMP CHelloWorldBHO::SetSite(IUnknown* pUnkSite) {
if (pUnkSite != NULL)
// 缓存指向 IWebBrowser2 的指针。
HRESULT hr = pUnkSite-&QueryInterface(IID_IWebBrowser2, (void **)&m_spWebBrowser);
if (SUCCEEDED(hr))
// 注册以从 DWebBrowserEvents2 中汇集事件。
hr = DispEventAdvise(m_spWebBrowser);
if (SUCCEEDED(hr))
m_fAdvised = TRUE;
// 取消注册事件汇。
if (m_fAdvised)
DispEventUnadvise(m_spWebBrowser);
m_fAdvised = FALSE;
// 在此释放缓存的指针和其他资源。
m_spWebBrowser.Release();
// 调用基类实现。
return IObjectWithSiteImpl&CHelloWorldBHO&::SetSite(pUnkSite); }
最后,添加一个简单的 OnDocumentComplete 事件处理程序。
void STDMETHODCALLTYPE CHelloWorldBHO::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL) {
// 从站点检索顶级窗口。
HRESULT hr = m_spWebBrowser-&get_HWND((LONG_PTR*)&hwnd);
if (SUCCEEDED(hr))
// 加载页面时输出消息框。
MessageBox(hwnd, L"大家好!", L"BHO", MB_OK);
请注意,消息框会将站点的顶层窗口用作其父窗口,而不仅仅是通过该参数传递 NULL。在 Internet Explorer 6 中,NULL 父窗口并不阻止应用程序,也就是说,在消息框等待用户输入时用户可以继续与浏览器交互。在某些情况下,这会导致浏览器挂起或崩溃。在 BHO 需要显示 UI 的这种少见情况下,应始终通过指定指向父窗口的句柄来确保该对话框为应用程序模态。
再一次试用
通过按 F5 再次启动 Internet Explorer。文档加载后,BHO 将显示其消息。
继续浏览以观察消息框出现的时间及频率。请注意,不仅在加载页面时会显示 BHO 警告,在通过单击&上一步&按钮重新加载该页面时也会显示 BHO 警告;但在单击&刷新&按钮时不会显示该警告。在 Internet Explorer 7 中,对于每个新的选项卡都会显示该消息框。
该事件在页面被下载和解析后激发,但是在
事件触发之前激发。在有多个框架的情况下,该事件将激发多次,结束时后面跟随的是顶层框架。在随后的代码中,通过将事件的 pDisp 参数所传递的对象与在 SetSite 中进行缓存处理的顶层浏览器进行比较来检测出这一系列事件的最后事件。
以下 JavaScript 代码演示了 DOM 的基本操作。它通过将图像的样式对象的
属性设置为&none&在网页上隐藏图像。
function RemoveImages(doc) {
var images = doc.
if (images != null)
for (var i = 0; i & images. i++)
var img = images.item(i);
img.style.display = "none";
在最后这部分中,我们将说明如何以 C++ 实现这个基本逻辑。
HelloWorldBHO.h
首先打开 HelloWorldBHO.h 并将 mshtml.h 包含在内。该头文件定义了使用 DOM 时所需的接口。
#include &mshtml.h&
// DOM 接口
接下来,定义专用成员方法以包含上述 JavaScript 的 C++ 实现。
void RemoveImages(IHTMLDocument2 *pDocument);
HelloWorldBHO.cpp
现在,OnDocumentComplete 事件处理程序要完成两个新任务。首先,它将缓存处理后的 WebBrowser 指针与激发事件的对象进行比较;如果两者相等,则该事件用于顶层窗口,并且文档也完全加载。其次,它检索一个指向
对象的指针并将其传递给 RemoveImages。
void STDMETHODCALLTYPE CHelloWorldBHO::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL) {
HRESULT hr = S_OK;
// 查询 IWebBrowser2 接口。
CComQIPtr&IWebBrowser2& spTempWebBrowser = pD
// 此事件是否与顶级浏览器相关联?
if (spTempWebBrowser && m_spWebBrowser &&
m_spWebBrowser.IsEqualObject(spTempWebBrowser))
// 从浏览器中获取当前文档对象&&
CComPtr&IDispatch& spDispD
hr = m_spWebBrowser-&get_Document(&spDispDoc);
if (SUCCEEDED(hr))
// &&并查询 HTML 文档。
CComQIPtr&IHTMLDocument2& spHTMLDoc = spDispD
if (spHTMLDoc != NULL)
// 最后,删除这些图像。
RemoveImages(spHTMLDoc);
pDisp 中的 IDispatch 指针包含了已在其中加载文档的窗口或框架的 IWebBrowser2 接口。我们将该值存储在 CComQIPtr 类变量中,该变量将自动执行一个 QueryInterface。接下来,为确定该页面是否已完全加载,我们将该接口指针与顶层浏览器在 SetSite 中进行缓存处理的接口指针进行比较。本测试的结果是,我们仅从顶层浏览器框架的文档中删除了图像;未加载到顶层框架中的文档没有通过本测试。(有关详细信息,请参阅。)
检索 HTML document 对象需要两个步骤。即使浏览器已经承载了另一种类型的文档对象(例如 Microsoft Word 文档),get_Document 也要为活动文档检索一个指针,因此,必须查询该活动文档是否有
接口,以确定它是否确实是 HTML 页面。通过 IHTMLDocument2 接口可以访问 DHTML DOM 的内容。
确认某 HTML 文档已加载后,将该值传递给 RemoveImages。请注意,该参数作为指针(而不是作为 CComPtr)传递给 IHTMLDocument2。
void CHelloWorldBHO::RemoveImages(IHTMLDocument2* pDocument) {
CComPtr&IHTMLElementCollection& spI
// 从 DOM 中获取图像集。
HRESULT hr = pDocument-&get_images(&spImages);
if (hr == S_OK && spImages != NULL)
// 获取集合中的图像数。
long cImages = 0;
hr = spImages-&get_length(&cImages);
if (hr == S_OK && cImages & 0)
for (int i = 0; i & cI i++)
CComVariant svarItemIndex(i);
CComVariant svarE
CComPtr&IDispatch& spdispI
// 按索引从集合中获取图像。
hr = spImages-&item(svarItemIndex, svarEmpty, &spdispImage);
if (hr == S_OK && spdispImage != NULL)
// 首先,查询通用 HTML 元素接口&&
CComQIPtr&IHTMLElement& spElement = spdispI
if (spElement)
// &&然后请求样式接口。
CComPtr&IHTMLStyle& spS
hr = spElement-&get_style(&spStyle);
// 设置 display="none" 以隐藏图像。
if (hr == S_OK && spStyle != NULL)
static const CComBSTR sbstrNone(L"none");
spStyle-&put_display(sbstrNone);
使用 C++ 与 DOM 交互要比使用 JavaScript 更繁琐,但代码流在本质上相同。
上述代码将循环访问图像集合中的每个项。在脚本中,很明显就可以看出是按序数还是按名称访问集合元素;但在 C++ 中,则必须通过传递一个空变量来手动区分这些参数。我们要再次依靠 ATL 帮助程序类(这次是 CComVariant)来将我们必须编写的代码量最小化。
最后的注意事项
为便于编写脚本,DOM 中的所有对象都使用 IDispatch 来提供从多个接口派生的属性和方法。但在 C++ 中,则必须要显式查询支持要使用的属性或方法的接口。例如,图像对象同时支持
接口。因此,要检索图像的 style 对象,首先必须查询 IHTMLElement 接口,该接口可提供 get_style 方法。
另请注意,COM 规则不能保证发生故障时指针的有效性;因此在每次 COM 调用后都需要检查 HRESULT。此外,对于许多 DOM 方法来说,返回 NULL 值并不是错误;因此需要对返回值和指针值都进行仔细检查。为使该检查更安全,应始终预先将指针初始化为 NULL。采用防御性的详细容错编码样式将有助于防止以后发生无法预测的程序错误。
虽然有各种类型的 BHO 用于多种用途,但所有 BHO 都有一个共同特点:与浏览器连接。由于 BHO 可以与 Internet Explorer 紧密集成,因此受到需要扩展浏览器功能的大量开发人员的重视。本文说明了如何创建一个简单 BHO 以用于在加载文档中修改 IMG 元素的样式属性。我们鼓励您根据自己需要将本文中的入门级示例继续延伸。可通过访问以下链接进一步探究这些可能性。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:907934次
积分:10015
积分:10015
排名:第1349名
原创:70篇
转载:374篇
评论:130条
(2)(13)(7)(12)(8)(5)(1)(4)(7)(5)(3)(8)(3)(1)(4)(4)(1)(3)(8)(5)(3)(1)(3)(3)(4)(7)(21)(3)(11)(6)(1)(2)(13)(8)(11)(6)(12)(26)(7)(16)(5)(13)(1)(2)(13)(6)(4)(8)(11)(4)(2)(9)(1)(1)(1)(3)(2)(5)(4)(3)(1)(1)(1)(6)(1)(1)(1)(3)(6)(2)(5)(2)(6)(1)(2)(3)(7)(6)(12)(1)(3)(12)(15)(5)}

我要回帖

更多关于 nx11帮助启动浏览器 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信