网站拦截器






3.84/5 (12投票s)
2006年3月7日
2分钟阅读

117260

1680
一篇关于可用于阻止特定站点的 BHO(浏览器帮助对象)的文章
引言
本文描述了如何使用 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 添加到“要阻止的网站”列表中。