2023年11月25日发(作者:)

目录

一,BHO开发概述 ............................................................. 2

1.1BHO的用途及实际应用 ................................................ 2

1.2BHO的工作原理及技术环境 ............................................ 2

二,框架设计 ................................................................. 3

2.1构建BHO框架......................................................... 3

2.2实现IOWS的接口方法 ......................................... 4

BJECTITHITE

三,注销SESSION ............................................................. 6

3.1BHO注册为浏览器的事件处理器 ....................................... 6

3.2监听浏览器关闭事件,并向S发送跳转指令 ........................... 7

ERVER

3.3关闭BHO注销页面 ..................................................... 8

3.4阻止文件浏览器加载BHO ............................................... 9

3.5向注册表中注册BHO组件 ............................................... 9

四,打包发布 ................................................................ 10

4.1BHO打包和找到关联D文件........................................... 10

LL

4.2编写自动安装脚本文件............................................. 11

INF

4.3工具打包。 .................................................. 11

CABARC

- 1 -

一,BHO开发概述

1.1 BHO的用途及实际应用

BHOBrowser Help Objects,是实现了特定接口的COM组件。BHO只适用于Windows系统下

IE浏览器和文件浏览器。开发好的BHO插件在注册表特定的位置注册好后,每当微软的浏览器启

动,BHO实例就会被创建。在浏览器工作的过程中,BHO会接收到很多事件,比如浏览器浏览新的地

址、前进或后退、生成新的窗口、浏览器退出等等。BHO可以在这些事件的响应中实现与浏览器的

交互。

本文档中我们将通过编写一个BHO实例来详细讲解BHO开发的一般流程。该实例的功能是:

用户成功登陆网站后,如果用户点击IE关闭按钮,BHO将捕获IE关闭事件,同时向Server发送一

个注销当前用户Session的请求。Server注销后跳转到BHO注销页面,BHO捕获到BHO注销页面时,

关闭该页面。

1.2 BHO的工作原理及技术环境

BHOCOM组件,而且一定实现了IObjectWithSite接口。这些组件除了在注册表中注册为COM

Server外,还必须将它们的CLSIDHKEY_LOCAL_MACHINESOFTWARE Windows CurrentVersion

ExplorerBrowser Helper Objects下注册为子键。微软在设计浏览器的时候,已经给这些组件预

留了空间。每当浏览器启动时,浏览器会首先在上述注册表位置查看是否有注册的 BHO CLSID;如

果有则分别创建一个实例,并对BHO实例进行初始化,建立交互连接。(注:BHO实例只有在创建它

的浏览器窗口销毁时才被释放。)图1.1演示了BHO的创建过程:

1.1

- 2 -

1.1 BHO支持的操作系统一览及IE一览

IE版本 操作系统版本 支持BHO

4.00

5.00

6.00

7.00

Windows 95 and Windows NT 4.0 IE4.0

Windows2000 IE和文件浏览器

WindowsXP IE和文件浏览器

Vista IE和文件浏览器

二,框架设计

2.1 构建BHO框架

开发环境: Microsoft Visual C++ 6.0

步骤1:建(WorkSpace)

步骤2:在中, ATL (Project)TEST

DLL2.1

2.1

- 3 -

步骤3:增加ATL对象类。在菜 InsertNew ATL 右键

ClassView 菜单)并Object ,选 Internet Exploer

2.2

2.2

步骤4:填写COM类的名称。只要输入Short Name,其它自动生成。见图2.3

2.3

2.2实现IObjectWithSite的接口方法

1:CComQIPtr&IID_IWebBrowser2>

mWebBrowser2(需要加入#include "ExDisp.h",用以保存浏览器组件的指针;DWORD

mCookie,用以保存与浏览器的连接ID。见图2.4

- 4 -

变量声明

2.4(详见MyBho.h文件)

步骤2:IObjectWithSite有两个接口方法:SetSiteGetSite。我们只需重载 SetSite

就行了。在ImyBho中增加函数声明SetSite函数。见图2.5

2.5

步骤3: 实现IDispatch接口方法。事件处理也就在IDispatch::Invoke中实现(各个事

件的IDExDispID.h中定义) BHO可能会接收到很多事件,但我们只需要响应我们感

兴趣的那一部分。首先在ImyBho中增加该函数的声明。见图2.6

- 5 -

2.6

步骤4: ImyBho添加RegisterEventHandlerBOOL inAdvise)方法声明,实现向IE

册和注销事件。详见附录代码。

通过上面的步骤,一个基本的BHO对象框架已经建立起来了。下一节来我们将根据具体要

实现的功能(Server发送注销Session命令)对代码主要功能作说明。

三,注销Session

3.1BHO注册为浏览器的事件处理器

注册BHO的事件的工作主要在SetSite函数中来完成。首先保存浏览器指针到mWebBrowser2

员变量中去。然后调用RegisterEventHandler函数向浏览器注册为事件处理器。见图3.1

/************************************************************

说明:SetSite(IUnknown *pUnkSite)IObjectWithSite接口的方法。

功能:1.保存浏览器组件指针,

向浏览器注册为事件处理器。

************************************************************/

STDMETHODIMP CMyBho::SetSite(IUnknown *pUnkSite){

if (pUnkSite){

//保存浏览器指针到mWebBrowser2成员变量中去。

mWebBrowser2 = pUnkSite;

if (mWebBrowser2){

//向浏览器注册为事件处理器。

return RegisterEventHandler(TRUE);

}

}

return E_FAIL;}

- 6 -

/**********************************************************

说明:自定义函数,用以注册/注销BHO事件。

功能:根据传入的参数TRUE/FALSE来向浏览器注册/注销BHO事件。

**********************************************************/

STDMETHODIMP CMyBho::RegisterEventHandler(BOOL inAdvise)

{

CComPtr spCP;

// 得到浏览器的连接点

CComQIPtr spCPC(mWebBrowser2);

HRESULT hr = spCPC->FindConnectionPoint(DIID_DWebBrowserEvents2, &spCP);

if (FAILED(hr)){

return hr;

}

if (inAdvise){

// 向浏览器注册事件。

hr = spCP->Advise(reinterpret_cast(this), &mCookie);

}else{

// 向浏览器注销事件。

spCP->Unadvise(mCookie);

}

return hr;

}

3.1(详见文件)

3.2监听浏览器关闭事件,并向Server发送跳转指令

监听浏览器事件,全部在Invoke函数中来完成。当捕获了浏览器退出事件(DISPID_ONQUIT)

时,首先取得页面的窗口名,判读是不是成功登陆页面。如果是,向Server LogOffAction发送

一组数据,通知ServerBHO注销事件。然后退出IE。见图3.2

case DISPID_ONQUIT:

{

//取得当前页面的标题。

BSTR lpHader = NULL;

mWebBrowser2->get_LocationName(&lpHader);

//如果是标题是“登录成功页面”的话,说明用户关闭的是已经登录的主页。

if (strstr( "登录成功页面", OLE2CA(lpHader))){

//需要跳转到ServerLogOutAction中去的URL

LPTSTR hostUrl = _T("localhost:8080/LogOff/");

//Server发送"action=BhoLogoff",提示是BHO注销事件。

LPTSTR postData = _T("action=BhoLogoff");

- 7 -

//取得POST数据长度。

int size = WideCharToMultiByte(CP_ACP, 0, A2COLE(postData), -1, 0, 0, 0, 0);

//为调用Navigate2方法定义参数。

VARIANT vURL;

VARIANT vFlags;

VARIANT vPostData;

VARIANT vHeaders;

VARIANT vNull;

//此处略去给参数赋值的代码,详见中的Invoke函数。

………………………………………………..

//跳转函数,并向Server发送数据。

mWebBrowser2->Navigate2(&vURL, &vFlags, &vNull, &vPostData, &vHeaders);

}

//注销BHO事件处理器。

RegisterEventHandler(FALSE);

break;

}

3.2(详见文件)

3.3关闭BHO注销页面

Server监听到BHO发来的注销命令时,Server注销当前用户的Session后,跳转到一个专

门的BHO注销页面(正常情况下是注销退出到登陆页面)BHO检测到IE已经跳转到BHO注销页面

时,就将窗口关闭。从而使用户对于注销过程可以忽视。见图3.3

3.3(详见文件)

}

break;

}

mWebBrowser2->Quit();

}

case DISPID_NAVIGATECOMPLETE2://监听页面跳转完毕事件

{//参数合法性检查

if (pDispParams->rgvarg[0].vt == (VT_BYREF|VT_VARIANT)){

char * strurl;

CComVariant varURL(*pDispParams->rgvarg[0].pvarVal);

Type(VT_BSTR);

strurl = OLE2A(l);

//如果发现当前的URLBHO注销页面,则关闭当前页面

if (strstr("localhost:8080/LogOff/", strurl)){

- 8 -

3.4阻止文件浏览器加载BHO

为了阻止文件浏览器加载BHO,在Dll入口函数DllMain中加入了判断。见图3.4

BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)

{

if (dwReason == DLL_PROCESS_ATTACH){

TCHAR pszLoader[MAX_PATH];

GetModuleFileName(NULL, pszLoader, MAX_PATH);

_tcslwr(pszLoader);

//检查是谁在载入,如果是文件浏览器,则退出。

if (_tcsstr(pszLoader, _T(""))) {

return FALSE;

}

_(ObjectMap, hInstance, &LIBID_TESTLib);

DisableThreadLibraryCalls(hInstance);

}else if (dwReason == DLL_PROCESS_DETACH){

_();

}

return TRUE; // ok

}

3.4(详见文件)

3.5向注册表中注册BHO组件

为了向注册表中注册BHO组件,还需要在中加入下面的代码。见图3.5

3.5(详见文件)

HKLM{

SOFTWARE{

Microsoft{

Windows{

CurrentVersion{

Explorer{

'Browser Helper Objects'{

{E5155767-23E5-4142-A63B-4DA81B196C36}}

}

}

}

}

}

}

到此,一个简单的注销SeesionBHO插件开发完毕了,当然还要在根据具体情况,Server

端加以判断才行。详细代码,请参考附录。

四,打包发布

经过前面的工作,这个BHO可以打包成CAB格式发布到网站了。当然还要在CAB包中编写一个

自动安装的脚步。当用户登录网站,就可以自动安装插件了。下面是详细步骤。

4.1 BHO打包和找到关联Dll文件

首先,BHO打包成Dll文件。VCBuild菜单中选择 Set Active Project Configuration

选项,然后再选中Win32 Release MinDependency选项,点击OK。如果此时编译发布出现error

LNK2001 错误的话,请到Project->Settings->C/C++中去除_ATL_MIN_CRT这个预处理符号。好了,

如果一切顺利的话。我们编译的Dll文件就存放到了我们的工程下的ReleaseMinDependency目录中

接下来,由于我们的Dll用到了一些VC自带的Dll库文件。而用户不一定有这些库文件,所

有要找到到底用了哪些库文件。这里我们使用VC自带的工具Dependency..Microsoft Visual

StudioCommonTools目录下)使用它打开我们刚编译好的Dll文件,就可以看到和它关联的所有

Dll文件。见图4.1

4.1

- 10 -

从图中可以看到,当前的Dll用到的VC库文件是 ,。然后我们在

Windows/System32目录下找到这两个个文件,复制。然后和生成的放到一个文件夹。

4.2编写自动安装脚本inf文件

由于我们的CAB包要自动下载安装到用户的电脑上面,所有必须要编写一个inf安装脚本。

inf自动安装脚本的说明,详见图4.2

固定格式

此处声明都有哪些文

件。注意顺序,被调用

dll要放到前面。

1. file值告诉ie到哪里去得到这个dll

2. 第二部分告诉声明支持的OS

3. 第三部分是CPU类型

4. thiscab说明在当前的cab文件

是否需要注册

DllCLSID。在VC

中的rgs文件中可以

找到。

4.2

4.3cabarc工具打包。

dll将要存到本地硬盘的位置,如果它的值是10

则将dll放到Windows或者WinNT下;如果是11

则放到WindowsSystem或者 WinNTSystem32

下;如果是空(就是没有值)则会放到Windows

或者WinNT下的Downloaded Program Files目录

下;

下载此工具/yule/meinv/179/

把刚才的文件都拷贝到该工具的BIN目录下面。执行如下命令: cabarc s 6144 N

。执行完毕后,会在此目录下生成一个包。

这个压缩包就可以发布到网站了。当然现在这个包没有经过任何签名,IE的默认安全策略下面是

执行不了的,解决办法是:1.把放包的网站设置为信任站点。 2.花钱买一个证书,一年费用好像是

5000多。当然我们是测试,所有采用第一种方式。

- 11 -

编写一个HTML文件,插入以下代码

<OBJECT ID="BhoTest" CLASSID="CLSID:

E5155767-23E5-4142-A63B-4DA81B196C36" CODEBASE="">OBJECT>

放到网站目录下。运行见图4.3

4.3

Windows/Systeme32的目录下面了。并且已经注册。再重启IE,我们的BHO就开始运行了。

:如需要删除BHO。请用 regsvr32 u “文件路径 + 文件名”来注销。然后就可以删除掉了。

- 12 -