首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

VC++ 開發 BHO (Browser Helper Object) 客製化 Internet Explorer

     編輯:VC 教學

前言

BHO (Browser Helper Object) 是實作特定 COM 介面的元件,隨 IE / 檔案總管啟動載入,能攔截瀏覽事件、修改 DOM、自訂工具列/選單、監控使用者行為。相較重寫瀏覽器,BHO 開發成本低、相容性好。本文示範使用 ATL 建立 BHO 實作網址過濾功能。

BHO 運作機制

  1. 註冊為 COM Server (標準 DllRegisterServer)。
  2. 在登錄表 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects 建立以 CLSID 為名的子機碼。
  3. IE/Explorer 啟動時掃描該機碼,對每個 CLSID CoCreateInstance 建立實例。
  4. 呼叫 IObjectWithSite::SetSite(IUnknown* pUnkSite),傳遞瀏覽器 IWebBrowser2 指標。
  5. BHO 向瀏覽器 IConnectionPointContainer 註冊事件接收 (DWebBrowserEvents2)。
  6. 瀏覽器觸發事件 (導航、文件完成、關閉等) → BHO IDispatch::Invoke 處理。

支援環境需求

Shell 版本OSIE 版本支援
4.00Win95/NT44.0僅 IE
4.71Win95/NT44.0IE + 檔案總管
4.72Win984.0IE + 檔案總管
5.00Win20005.0IE + 檔案總管

注意:BHO 僅支援 IE (Trident 引擎),不支援 Edge (Chromium)、Chrome、Firefox。

ATL 專案建立步驟

1. 建立 ATL COM 專案

  • VC6: ATL COM AppWizard → 專案名 BhoPlugin → 預設設定 (Dynamic Link to ATL)。
  • 安裝 Platform SDK (含 Internet Development SDK)。

2. 新增 ATL 物件 (IE Object)

  • Insert → New ATL Object → Internet Explorer Object。
  • Short Name: EyeOnIE → 類別 CEyeOnIE,基類含 IObjectWithSiteImpl。

3. 實作 IObjectWithSite::SetSite

EyeOnIE.h 新增成員:


#include  // IWebBrowser2 定義
#include  // 事件 DISPID 定義

class ATL_NO_VTABLE CEyeOnIE :
    public CComObjectRootEx,
    public CComCoClass,
    public IObjectWithSiteImpl,
    public IDispatchImpl
{
    CComQIPtr m_spWebBrowser2;
    DWORD m_dwCookie; // 事件連線 Cookie

public:
    STDMETHOD(SetSite)(IUnknown* pUnkSite);
    // ...
};

EyeOnIE.cpp 實作:


STDMETHODIMP CEyeOnIE::SetSite(IUnknown* pUnkSite)
{
    // 1. 呼叫基類實作 (處理站點設定/清除)
    HRESULT hr = IObjectWithSiteImpl::SetSite(pUnkSite);
    if (FAILED(hr)) return hr;

    if (pUnkSite) // 啟動階段
    {
        // 取得 IWebBrowser2
        m_spWebBrowser2 = pUnkSite;
        if (!m_spWebBrowser2) return E_NOINTERFACE;

        // 註冊事件接收
        CComQIPtr spCPC = m_spWebBrowser2;
        if (spCPC)
        {
            CComPtr spCP;
            spCPC->FindConnectionPoint(DIID_DWebBrowserEvents2, &spCP);
            if (spCP)
                spCP->Advise(GetUnknown(), &m_dwCookie);
        }
    }
    else // 關閉階段
    {
        // 取消事件註冊
        if (m_spWebBrowser2 && m_dwCookie)
        {
            CComQIPtr spCPC = m_spWebBrowser2;
            if (spCPC)
            {
                CComPtr spCP;
                spCPC->FindConnectionPoint(DIID_DWebBrowserEvents2, &spCP);
                if (spCP) spCP->Unadvise(m_dwCookie);
            }
            m_dwCookie = 0;
        }
        m_spWebBrowser2.Release();
    }
    return S_OK;
}

4. 實作 IDispatch::Invoke 處理事件

僅處理感興趣事件,範例:DISPID_BEFORENAVIGATE2 (導航前) 實作網址過濾。


STDMETHODIMP CEyeOnIE::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
    WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
    EXCEPINFO* pExcepInfo, UINT* puArgErr)
{
    if (dispIdMember == DISPID_BEFORENAVIGATE2)
    {
        // 參數順序: pDisp, URL, Flags, TargetFrameName, PostData, Headers, Cancel
        if (pDispParams->cArgs >= 7)
        {
            VARIANT* pUrl = &pDispParams->rgvarg[5]; // URL 在倒數第 2 (索引 5)
            VARIANT* pCancel = &pDispParams->rgvarg[0]; // Cancel 在索引 0

            if (pUrl->vt == VT_BSTR && pCancel->vt == (VT_BYREF | VT_BOOL))
            {
                CString strUrl(pUrl->bstrVal);
                strUrl.MakeLower();
                if (strUrl.Find(_T("girl.com")) != -1) // 過濾關鍵字
                {
                    *pCancel->pboolVal = VARIANT_TRUE; // 取消導航
                    MessageBox(NULL, _T("此網站被封鎖!"), _T("BHO 過濾"), MB_ICONWARNING);
                }
            }
        }
        return S_OK;
    }
    else if (dispIdMember == DISPID_QUIT) // 瀏覽器關閉
    {
        // 已在 SetSite(nullptr) 中處理取消註冊
    }
    return S_OK;
}

5. 防止載入至檔案總管 (可選)

在 DllMain 判斷載入進程:


extern "C" BOOL WINAPI DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID)
{
    if (dwReason == DLL_PROCESS_ATTACH)
    {
        TCHAR szPath[MAX_PATH];
        GetModuleFileName(NULL, szPath, MAX_PATH);
        CString strPath(szPath); strPath.MakeLower();
        if (strPath.Find(_T("explorer.exe")) != -1)
            return FALSE; // 拒絕載入至檔案總管
    }
    return _Module.DllMain(dwReason, 0);
}

6. 修改註冊腳本 EyeOnIE.rgs 加入 BHO 登錄


HKLM
{
    SOFTWARE
    {
        Microsoft
        {
            Windows
            {
                CurrentVersion
                {
                    Explorer
                    {
                        'Browser Helper Objects'
                        {
                            '{YOUR_CLSID_HERE}' // 替換為實際 CLSID
                        }
                    }
                }
            }
        }
    }
}

部署與測試

  1. 建置專案產生 BhoPlugin.dll。
  2. 管理員權限執行 regsvr32 BhoPlugin.dll 註冊。
  3. 啟動 IE,嘗試瀏覽含 girl.com 的網址,應彈出封鎖訊息並取消導航。
  4. 移除:regsvr32 /u BhoPlugin.dll 或刪除登錄表對應 CLSID。

進階功能延伸

  • DOM 操作:取得 IHTMLDocument2 注入腳本、修改頁面內容。
  • 工具列/按鈕:實作 IDeskBand、IInputObject 建立 Explorer Bar。
  • 右鍵選單擴充:實作 IContextMenu 註冊 Shell Extension。
  • 下載攔截:處理 DISPID_DOWNLOADBEGIN 等事件。

結語

BHO 是 IE 時代客製化瀏覽器的標準技術。雖現代瀏覽器已棄用 (Edge/Chrome 使用 Extension API),但在企業舊系統維護、IE Mode 相容場景仍具實用價值。掌握 COM、連接點、事件處理流程,可快速建構強大的瀏覽器增益集。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved