程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++中使用BHO來屏蔽特定網站

C++中使用BHO來屏蔽特定網站

編輯:關於C++

BHO(浏覽器輔助對象)是一種簡單的ATL COM對象,而Internet Explorer會在每次運行時都加載它;換句話來說,即每個Internet Explorer的實例都會加載它。BHO運行在Internet Explorer的地址空間內,能對可訪問的對象(如窗口、模塊等等)執行任何操作,且因為它依附於浏覽器的主窗口,所以其生命期與浏覽器實例的生命期一致。

如果在系統中打開了活動桌面,BHO也能隨同Windows Explorer一起啟動。如果不想在Windows Explorer中運行BHO,可將如下代碼添加到DLLMain中:

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

BHO的COM Server必須實現IObjectWithSite,以便對象可以掛鉤到浏覽器事件,Internet Explorer會依靠IObjectWithSite將一個指針傳遞到它的IUnknown接口,所以,只需實現IObjectWithSite的SetSite方法就行了,如下所示:

STDMETHODIMP CBhoApp::SetSite(IUnknown *pUnkSite)
{
 //獲取並存儲IWebBrowser2指針
 m_spWebBrowser2 = pUnkSite;
 if (m_spWebBrowser2 == NULL)
  return E_INVALIDARG;
 //獲取並存儲IConnectionPointerContainer指針
 m_spCPC = m_spWebBrowser2;
 if (m_spCPC == NULL)
  return E_POINTER;
 //連接到宿主程序以接收事件通知
 return Connect();
}

以下是Connect函數比較簡單的實現:

HRESULT CBhoApp::Connect()
{
 HRESULT hr;
 CComPtr<IConnectionPoint> spCP;
 //獲取訪問WebBrowser事件的連接指針
 hr = m_spCPC->FindConnectionPoint(DIID_DWebBrowserEvents2, &spCP);
 if (FAILED(hr))
  return hr;
 //把事件處理程序傳遞給宿主程序Each time an event
 //每次有事件產生時,宿主程序都會調用我們實現的IDispatch接口的函數
 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)
{
  //在使用ATL字符串轉換宏(此處用的是OLE2T)防止編譯錯誤時,必須先調用這個宏
  USES_CONVERSION;
  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));
   //此處,直接比較www.xyz.com,也可從一個要屏蔽的網站列表中進行比較。
   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_FALSE;
   }
   return S_OK;
  }
  else if(dispidMember == DISPID_NAVIGATECOMPLETE2)
  //檢查以防止頁面的post導航加載(post-navigation loading)
  {
   BSTR bstrUrlName;
   HRESULT hr = m_spWebBrowser2->get_LocationURL(&bstrUrlName);
   if(FAILED(hr))
    return hr;
   //把文本從Unicode轉換為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注冊組件,如果想卸載,只需在regsvr32後帶上/u。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved