VC++开发BHO插件

来源:互联网 发布:安卓6.0的数据库在哪 编辑:程序博客网 时间:2024/05/20 05:26

首先介绍一下什么是BHO?

     BHO(Browser Help Objects),是实现了特定接口的COM组件。开发好的BHO插件在注册表特定的位置注册好后,每当微软的浏览器启动,BHO实例就会被创建。在浏览器工作的工程中,BHO会接收到很多事件,比如浏览器浏览新的地址、前进或后退、生成新的窗口、浏览器退出等等;BHO可以在这些事件的响应中实现与浏览器的交互。

     在Windows操作系统上,我们最常见的浏览器有两种:文件浏览器(exploer.exe,应用于文件系统)和Internet浏览器(iexplore.exe,应用于互联网资源)。由于这两个浏览器功能强大,而且又与Windows操作系统捆绑销售,最终也就成为了浏览器的标准。但有时候,为了给浏览器加入一些新的特性,我们往往会重新设计一个自己的浏览器。新的浏览器模仿标准浏览器的大部分功能,同时加入新特性。这种做法最直观,但实际上也是相对于微软的重复劳动,且工作量比较大。其实,使用BHO插件,一切都变得很简单。
      每当浏览器启动时,浏览器会首先在上述注册表位置查看是否有注册的BHO CLSID;如果有则分别创建一个实例,并对BHO实例进行初始化,建立交互连接。(注:BHO实例只有在创建它的浏览器窗口销毁时才被释放。)成功创建的BHO,不仅可以得到各种标准的浏览器操作事件,并做出响应;还可以定制浏览器的菜单、工具条等界面元素;更或者可以安装钩子函数,监视浏览器的一举一动。值得注意的是,使用BHO插件,Internet浏览器要求在4.0以上版本;如果是文件浏览器,操作系统要求是Windows 95/98/2000或Window NT 4.0以上版本,并且Shell的版本在4.71以上。下面是支持BHO特性的系统一览表:

      Shell版本 操作系统版本 支持BHO 
     4.00 Windows 95 and Windows NT 4.0(IE版本为 4.0) 仅IE4.0 
     4.71 Windows 95 and Windows NT 4.0(IE版本为 4.0) IE和文件浏览器 
     4.72 Windows 98 IE和文件浏览器 
     5.00  Windows 2000 IE和文件浏览器 

 

下面一步一步的介绍怎么样用vc来制作自己的BHO

(开发环境为VC6.0(使用ATL),安装Platform SDK中的Internet Development SDK)

第一步,增加一个ATL Object到该项目中。

在VC菜单Insert->New ATL Object…,在弹出的对话框中选择“Internet Explorer Object”,输入COM类名(在Short Name后输入EyeOnIE,其它各项会自动生成)。完成后,我们可以看到CEyeOnIE类有一个基类IObjectWithSiteImpl,这个就是实现IObjectWithSite接口的模版类。

 

第二步,实现IObjectWithSite的接口方法。

在 “EyeOnIE.h” 文件中,添加以下内容:

 

///////////////////////////////////////////////////////////////////////////////////////////

   #include "ExDisp.h"

 

   CComQIPtr<IWebBrowser2, &IID_IWebBrowser2> mWebBrowser2; //用以保存浏览器组件的指针

   DWORD mCookie;//用以保存与浏览器的连接ID

   STDMETHOD(SetSite)(IUnknown *pUnkSite);
   HRESULT RegisterEventHandler(BOOL inAdvise);
   STDMETHODIMP Invoke(DISPID dispidMember,REFIID riid, LCID lcid, WORD wFlags,

                                         DISPPARAMS * pDispParams, VARIANT * pvarResult,

                                         EXCEPINFO * pexcepinfo, UINT * puArgErr);

 

//////////////////////////////////////////////////////////////////////////////////////////////////

 

在 “EyeOnIE.cpp” 文件中,添加定义:

 

///////////////////////////////////////////////////////////////////////////////////

STDMETHODIMP CEyeOnIE::SetSite(IUnknown *pUnkSite)
{
 USES_CONVERSION;

 if (pUnkSite)
 {
  mWebBrowser2 = pUnkSite;
  if (mWebBrowser2)
  {
   return RegisterEventHandler(TRUE);
  }
 }
 return E_FAIL;
}

 

 

HRESULT CEyeOnIE::RegisterEventHandler(BOOL inAdvise)
{
 CComPtr<IConnectionPoint> spCP;
 // Receives the connection point for WebBrowser events
 CComQIPtr<IConnectionPointContainer, &IID_IConnectionPointContainer> spCPC(mWebBrowser2);
 HRESULT hr = spCPC->FindConnectionPoint(DIID_DWebBrowserEvents2, &spCP);
 if (FAILED(hr))
  return hr;

 if (inAdvise)
 {
  // Pass the event handlers to the container
  hr = spCP->Advise(reinterpret_cast<IDispatch*>(this), &mCookie);
 }
 else
 {
  spCP->Unadvise(mCookie);
 }
 return hr;
}

 

STDMETHODIMP CEyeOnIE::Invoke(DISPID dispidMember,REFIID riid, LCID lcid,
         WORD wFlags, DISPPARAMS * pDispParams,
         VARIANT * pvarResult,EXCEPINFO * pexcepinfo, UINT * puArgErr)
{
 USES_CONVERSION;

 if (!pDispParams)
  return E_INVALIDARG;

 switch (dispidMember)
 {
  //
  // The parameters for this DISPID are as follows:
  // [0]: Cancel flag - VT_BYREF|VT_BOOL
  // [1]: HTTP headers - VT_BYREF|VT_VARIANT
  // [2]: Address of HTTP POST data - VT_BYREF|VT_VARIANT
  // [3]: Target frame name - VT_BYREF|VT_VARIANT
  // [4]: Option flags - VT_BYREF|VT_VARIANT
  // [5]: URL to navigate to - VT_BYREF|VT_VARIANT
  // [6]: An object that evaluates to the top-level or frame
  // WebBrowser object corresponding to the event.
  //
  case DISPID_BEFORENAVIGATE2:
  {
   LPOLESTR lpURL = NULL;
   mWebBrowser2->get_LocationURL(&lpURL);
   char * strurl;
   if (pDispParams->cArgs >= 5 && pDispParams->rgvarg[5].vt == (VT_BYREF|VT_VARIANT))
   {
    CComVariant varURL(*pDispParams->rgvarg[5].pvarVal);
    varURL.ChangeType(VT_BSTR);
    strurl = OLE2A(varURL.bstrVal);
   }
   if (strstr(strurl, "mm.com"))
   {
    *pDispParams->rgvarg[0].pboolVal = TRUE;
    ::MessageBox(NULL, _T("该网页已被禁止!"),_T("Warning"),MB_ICONSTOP);
    return S_OK;
   }
   break;
  }

  case DISPID_NAVIGATECOMPLETE2:
   break;
  case DISPID_DOCUMENTCOMPLETE:
   break;
  case DISPID_DOWNLOADBEGIN:
   break;
  case DISPID_DOWNLOADCOMPLETE:
   break;
  case DISPID_NEWWINDOW2:
   break;
  case DISPID_QUIT:
   //::MessageBox(NULL, _T("该网页已被禁止!"),_T("Warning"),MB_ICONSTOP);
   RegisterEventHandler(FALSE);
   break;
  default:
   break;
 }

 return S_OK;
}

 

///////////////////////////////////////////////////////////////////////////////////////////////////////
 

第三步,限制插件的使用范围

     如果不想此插件随文件浏览器启动,那么可以在dllMain函数中进行过滤。可以将主文件中的dllMain函数改成以下:

 

///////////////////////////////////////////////////////////////////////////////////////////////////

 

extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
{
 if (dwReason == DLL_PROCESS_ATTACH)
 {
  // Check who's loading us.
  // If it's Explorer then "no thanks" and exit...
  TCHAR pszLoader[MAX_PATH];
  GetModuleFileName(NULL, pszLoader, MAX_PATH);
  _tcslwr(pszLoader);
  if (_tcsstr(pszLoader, _T("explorer.exe")))
   return FALSE;

  _Module.Init(ObjectMap, hInstance, &LIBID_BHOPLUGINLib);
  DisableThreadLibraryCalls(hInstance);
 }
 else if (dwReason == DLL_PROCESS_DETACH)
  _Module.Term();
 return TRUE; // ok
}

 

/////////////////////////////////////////////////////////////////////////////////////////////////////////////

 

至此,一个简单的BHO插件完成了。下面要进行的工作就是让插件随IE启动。

这里我们要完成两个工作。

1. 将插件CLSID添加到注册表相应位置

首先打开工程中自动生成的文件“EyeOnIE.rgs”,在此文件中会看到以下内容:

 

/////////////////////////////////////////////////////////////////////////////////////////////////////

 

HKCR
{
 BhoPlugin.EyeOnIE.1 = s 'EyeOnIE Class'
 {
  CLSID = s '{CF0910A2-E944-4F85-8985-941C74CCC895}'
 }
 BhoPlugin.EyeOnIE = s 'EyeOnIE Class'
 {
  CLSID = s '{CF0910A2-E944-4F85-8985-941C74CCC895}'
  CurVer = s 'BhoPlugin.EyeOnIE.1'
 }
 NoRemove CLSID
 {
  ForceRemove {CF0910A2-E944-4F85-8985-941C74CCC895} = s 'EyeOnIE Class'
  {
   ProgID = s 'BhoPlugin.EyeOnIE.1'
   VersionIndependentProgID = s 'BhoPlugin.EyeOnIE'
   ForceRemove 'Programmable'
   InprocServer32 = s '%MODULE%'
   {
    val ThreadingModel = s 'Apartment'
   }
   'TypeLib' = s '{61D0DCC4-2663-4D44-B909-2663CADD57B5}'
  }
 }
}

 

//////////////////////////////////////////////////////////////////////////////////////////////////////

 

这里的 {CF0910A2-E944-4F85-8985-941C74CCC895} 是我们插件的CLSID,我们要在注册表相应位置添加此CLSID。

具体步骤如下:

在“开始”->“运行” 输入 “regedit.exe”

在弹出的注册表编辑器中找到以下路径:HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/ CurrentVersion/Explorer/Browser Helper Objects

在“Browser Helper Objects”上右键,选择 “新建”->“项”

在弹出的对话框中输入 {CF0910A2-E944-4F85-8985-941C74CCC895} 即插件的CLSID,然后确定即可。

 

2. 向系统注册插件

在“开始”->“运行” 输入 “regsvr32  D:/测试环境/BhoPlugin/Debug/BhoPlugin.dll”,点击 确定。

注意: D:/测试环境/BhoPlugin/Debug/BhoPlugin.dll  是插件dll的绝对路径。

 

完成这两步后,我们的插件就会随IE启动,此时在IE的地址栏中输入含有 “mm.com” 的地址,看看会有什么效果。

 

如果不想使用此插件可以在“运行”中输入 “regsvr32 /u D:/测试环境/BhoPlugin/Debug/BhoPlugin.dll”,点击确定即可卸载插件。在注册表中删除我们插件的CLSID,也可以停止插件的使用。

 

 

以上只是BHO的很简单的应用,其实BHO的功能还有很多,比如网页内容分析、IE界面定制等等,这些内容将在以后陆续更新。

原创粉丝点击