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

C++ 開發 BHO (Browser Helper Object) 封鎖特定網站完整指南

     編輯:關於C++

什麼是 BHO?

BHO (Browser Helper Object) 是實作 IObjectWithSite 的 ATL COM 物件。Internet Explorer 啟動時會載入所有已註冊的 BHO,每個 IE 實例各載入一次。BHO 運行於 IE 進程位址空間,可存取視窗、文件物件模型 (DOM) 等一切 IE 內部資源,生命週期與 IE 實例綁定。

核心介面:IObjectWithSite::SetSite

IE 呼叫 SetSite(IUnknown* pUnkSite) 傳遞自身 IUnknown。BHO 必須:

  1. QueryInterface 取得 IWebBrowser2(控制瀏覽器核心)
  2. QueryInterface 取得 IConnectionPointContainer(事件連接)
  3. 呼叫 Advise 訂閱 DWebBrowserEvents2 事件

STDMETHODIMP CBho::SetSite(IUnknown* pUnkSite) {
    m_spWebBrowser2 = pUnkSite;           // 取得 IWebBrowser2
    if (!m_spWebBrowser2) return E_INVALIDARG;

    m_spCPC = m_spWebBrowser2;            // 取得 IConnectionPointContainer
    if (!m_spCPC) return E_POINTER;

    return Connect();                     // 連接事件
}

事件連接與處理

建立連接點


HRESULT CBho::Connect() {
    CComPtr spCP;
    HRESULT hr = m_spCPC->FindConnectionPoint(DIID_DWebBrowserEvents2, &spCP);
    if (FAILED(hr)) return hr;

    // 將自身 (IDispatch) 註冊為事件接收器
    return spCP->Advise(static_cast(this), &m_dwCookie);
}

實作 IDispatch::Invoke 攔截導航事件


STDMETHODIMP CBho::Invoke(DISPID dispid, REFIID, LCID, WORD,
                          DISPPARAMS* pDispParams, VARIANT* pVarResult,
                          EXCEPINFO*, UINT*) {
    USES_CONVERSION;
    if (dispid == DISPID_BEFORENAVIGATE2 || dispid == DISPID_NAVIGATECOMPLETE2) {
        // 取得目前 URL
        CComBSTR bstrUrl;
        if (FAILED(m_spWebBrowser2->get_LocationURL(&bstrUrl))) return S_OK;

        CComPtr spDisp;
        if (pDispParams->cArgs > 0 && pDispParams->rgvarg[0].vt == VT_DISPATCH)
            spDisp = pDispParams->rgvarg[0].pdispVal; // 目標框架

        // 比對封鎖清單(此處簡化為硬編碼)
        if (_wcsicmp(bstrUrl, L"https://www.xyz.com/") == 0) {
            VARIANT vFlags = {0}, vTarget = {0};
            // 導向空白頁或自訂封鎖頁
            m_spWebBrowser2->Navigate(SysAllocString(L"about:blank"), &vFlags, &vTarget, NULL, NULL);
            m_spWebBrowser2->put_Visible(VARIANT_TRUE);
            if (pVarResult) pVarResult->vt = VT_BOOL, pVarResult->boolVal = VARIANT_TRUE; // 取消導航
            return S_FALSE;
        }
    }
    return S_OK;
}

關鍵事件:

  • DISPID_BEFORENAVIGATE2:導航前,可取消
  • DISPID_NAVIGATECOMPLETE2:導航完成,可二次檢查(防 POST 重導)

註冊表部署

專案 .rgs 檔加入:


HKLM {
    NoRemove Software {
        NoRemove Microsoft {
            NoRemove Windows {
                NoRemove CurrentVersion {
                    NoRemove Explorer {
                        NoRemove "Browser Helper Objects" {
                            ForceRemove {YOUR_CLSID_HERE} = s "Your BHO Description"
                        }
                    }
                }
            }
        }
    }
}

編譯產出 DLL 後:


regsvr32 YourBho.dll      // 註冊
regsvr32 /u YourBho.dll   // 解除註冊

避免載入 Windows Explorer

BHO 預設也會隨 Active Desktop 載入 explorer.exe。若僅針對 IE:


BOOL WINAPI DllMain(HINSTANCE, DWORD reason, LPVOID) {
    if (reason == DLL_PROCESS_ATTACH) {
        TCHAR path[MAX_PATH];
        GetModuleFileName(NULL, path, MAX_PATH);
        if (_tcsicmp(_tcsrchr(path, '\\')+1, _T("explorer.exe")) == 0)
            return FALSE;  // 拒絕載入
    }
    return TRUE;
}

完整專案結構要點

  • ATL COM DLL 專案(Visual Studio:ATL Project → DLL)
  • 實作 IObjectWithSite、IDispatch
  • SetSite 取得 IWebBrowser2 + 事件連接
  • Invoke 攔截 BEFORENAVIGATE2/NAVIGATECOMPLETE2
  • URL 比對邏輯可擴充為從登錄檔/檔案讀取封鎖清單
  • .rgs 註冊 BHO CLSID 至 HKLM\...\Browser Helper Objects

現代替代方案提示

IE 已停止維護,Edge 採用 WebView2 / 擴充功能 (Manifest V3) 架構。新專案請考慮:

  • Edge 擴充功能:跨平台、標準化、安全沙箱
  • WebView2 應用程式:嵌入 Edge 引擎,完全可控
  • 網路層過濾:WFP (Windows Filtering Platform) / 透明 Proxy

BHO 僅適用於維護舊版 IE 相容系統。

總結

BHO 透過 COM 機制深度整合 IE,攔截導航事件實現 URL 封鎖。核心流程:SetSite → IWebBrowser2 → IConnectionPointContainer → Advise → Invoke 處理事件。雖技術成熟,但 IE 退役意味著 BHO 已成歷史,新開發請轉向現代瀏覽器擴充生態。

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