65.9K
CodeProject 正在变化。 阅读更多。
Home

网站拦截器

2006年3月7日

2分钟阅读

viewsIcon

117260

downloadIcon

1680

一篇关于可用于阻止特定站点的 BHO(浏览器帮助对象)的文章

下载源代码 - 16.82 KB

引言

本文描述了如何使用 BHO(浏览器助手对象)来阻止特定的网站。

背景

BHO 是一个简单的 ATL COM 对象,每次 Internet Explorer 运行时都会加载它,即对于 Internet Explorer 的每个实例。BHO 在 Internet Explorer 的地址空间中运行,可以对可用对象(窗口、模块等)执行任何操作。BHO 与浏览器的实例一起实例化和销毁,因为它绑定到浏览器的主窗口。

如果您的系统启用了活动桌面,BHO 也会与 Windows 资源管理器一起实例化。要禁用 Windows 资源管理器中的 BHO,您可以将以下代码片段添加到 DllMain 中:

TCHAR strLoader[MAX_PATH];

::GetModuleFileName (NULL, strLoader, MAX_PATH);
if(stricmp("explorer.exe", strLoader) == 0)
 return FALSE;

BHO 的 COM 服务器必须实现 IObjectWithSite,这将帮助我们的对象挂接到浏览器的事件上。Internet Explorer 将通过 IObjectWithSite 的方式传递对其 IUnknown 接口的指针。只需要实现 IObjectWithSite 的 SetSite 方法,如下所示:

STDMETHODIMP CBhoApp::SetSite(IUnknown *pUnkSite)
{
  // Retrieve and store the IWebBrowser2 pointer 
  m_spWebBrowser2 = pUnkSite; 
  if (m_spWebBrowser2 == NULL)
   return E_INVALIDARG;

  // Retrieve and store the IConnectionPointerContainer pointer 
  m_spCPC = m_spWebBrowser2;
  if (m_spCPC == NULL)
   return E_POINTER;

   // Connect to the container for receiving event notifications
  return Connect();
}

这里的 connect 函数看起来像这样:

HRESULT CBhoApp::Connect()
{
  HRESULT hr;
  CComPtr<IConnectionPoint> spCP;

  // Receives the connection point for WebBrowser events
  hr = m_spCPC->FindConnectionPoint(DIID_DWebBrowserEvents2, &spCP);
  if (FAILED(hr))
   return hr;

  // Pass our event handlers to the container. Each time an event occurs
  // the container will invoke the functions of the IDispatch interface 
  // we implemented.
  hr = spCP->Advise(reinterpret_cast<IDispatch*>(this),&m_dwCookie);
  
  return hr; 
}

通过调用 Advise 方法,我们告诉浏览器 BHO 渴望接收有关事件的通知。这意味着 BHO 将向浏览器提供指向 IDispatch 的指针(这是由于组件的事件处理)。然后,浏览器调用 IDispatch 的 Invoke 方法,并将事件的 ID 作为参数传递给它。因此,我们的 BHO 必须实现 Invoke 方法来处理事件。

STDMETHODIMP CBhoApp::Invoke(DISPID dispidMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT   
    *pvarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
 USES_CONVERSION; //This macro should be called when using ATL string conversion 
     //macros to avoid compile time errors (here we are using OLE2T)
 
 if(dispidMember == DISPID_BEFORENAVIGATE2)
 {
  BSTR bstrUrlName;
  HRESULT hr = m_spWebBrowser2->get_LocationURL(&bstrUrlName);
  if(FAILED(hr))
   return hr;

  LPTSTR psz = new TCHAR[SysStringLen(bstrUrlName)];
  lstrcpy(psz, OLE2T(bstrUrlName));

  // Here, I am directly comparing with xyz.com. You can maintain a list of all sites to 
  // be blocked and then compare. Or you can also keep this data in a database, but I guess
  // that might affect the performance. (Experts! please comment on this.)


  if(stricmp("http://www.xyz.com/",(const%20char%20*)psz) == 0) 
  // Here you can also use strstr instead of stricmp
  // which will help to allow all domain originating from xyz. 
  {
     VARIANT vFlags = {0},vTargetFrameName = {0};
     // Instead of “about:blank”, you can redirect user to some page saying site has been blocked. :-)
     m_spWebBrowser2->Navigate(SysAllocString(L"about:blank"),&vFlags,&vTargetFrameName,NULL,NULL);
     m_spWebBrowser2->put_Visible(VARIANT_TRUE);
     return S_FALSE;
  }
  return S_OK;
 }
 else if(dispidMember == DISPID_NAVIGATECOMPLETE2) 
 // This checking is done to avoid post-navigation
 // loading of a page. 
 {
  BSTR bstrUrlName;
  HRESULT hr = m_spWebBrowser2->get_LocationURL(&bstrUrlName);
  if(FAILED(hr))
   return hr;

  // Convert the text from Unicode to ANSI
  LPTSTR psz = new TCHAR[SysStringLen(bstrUrlName)];
  lstrcpy(psz, OLE2T(bstrUrlName));
  ::OutputDebugString("In Navigate Complete");
  ::OutputDebugString(psz);
  if(stricmp("http://www.xyz.com/",psz) == 0)
  {
   VARIANT vFlags = {0},vTargetFrameName = {0};
   m_spWebBrowser2->Navigate(SysAllocString(L"about:blank"),&vFlags,&vTargetFrameName,NULL,NULL);
   m_spWebBrowser2->put_Visible(VARIANT_TRUE);
  }
  return S_OK;
 }
 return S_FALSE;
}

您还需要更改项目的 .rgs 文件。将以下代码片段添加到其中:

HKLM
{
   SOFTWARE
   {
      Microsoft
      {
         Windows
         {
            CurrentVersion
            {
               Explorer
               {
                  'Browser Helper Objects'
                  {
                     ForceRemove {0CB66BA8-5E1F-4963-93D1-E1D6B78FE9A2}
                  }
               }
            }
         }
      }
   }
}

使用代码

完成编译后,使用 regsvr32 注册您的组件。每当您想要禁用 BHO 时,只需使用带有 /u 选项的 regsvr32。还可以提供一个简单的 UI 来执行此操作。

改进

  • 可以添加一个 UI 元素来将 URL 添加到“要阻止的网站”列表中。

参考文献

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwebgen/html/bho.asp.
© . All rights reserved.