from:http://dohkoos.name/?p=429
最近忽然突發奇想,想統計一下我最經常上的網站是哪些,並且在這些網站上都停留了多久。為此決定寫一個BHO外掛程式來做這件事。
BHO(Browser Help Objects)是實現了特定介面(IObjectWithSite)的COM組件。開發好的BHO外掛程式除了要在註冊表中註冊為COM Server外,還必須將它的CLSID在HKLMSOFTWARE...Browser Helper Objects下註冊為子鍵。每當瀏覽器[1]啟動時,首先會在上述註冊表位置查看是否有註冊的BHO CLSID,如果有則分別建立一個執行個體,並對BHO執行個體進行初始化。BHO執行個體運行在瀏覽器的地址空間內,能對可訪問的對象(如視窗、模組等等)執行任何操作,且因為它依附於瀏覽器的主視窗,所以其生命週期與瀏覽器執行個體的生命週期一致。示範了BHO的建立過程:
下面就來介紹一下如何開發BHO外掛程式。首先建立一個C#項目,類型為Class Library。然後將Class1.cs改名為IObjectWithSite.cs,還要給IObjectWithSite添加兩個功能:GetSite和SetSite。
Public Interface Iobjectwithsite
{
[Preservesig]
Int Setsite([Marshalas(Unmanagedtype.Iunknown)]Object Site);
[Preservesig]
Int Getsite(Ref Guid Guid, Out Intptr Ppvsite);
}
添加一個cs檔案UrlTrack.cs,並且實現IObjectWithSite介面。使用BHO還需要添加兩個引用SHDocVw.dll和MSHTML.dll,可以在WindowsSystem32目錄下找到。
在IObjectWithSite.cs中,還需要為我們的程式指出IE的GUID,使得它可以掛接(attach)到IE上
[
ComVisible(true),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid("FC4801A3-2BA9-11CF-A229-00AA003D7352")
]
另外,還需要給BHO程式分配一個GUID,這個可以通過System.Guid.NewGuid()方法得到
[
ComVisible(true),
Guid("e90da13b-117a-4178-8111-0f712da09ff9"),
ClassInterface(ClassInterfaceType.None)
]
在UrlTrack.cs中,我們還需要寫兩個方法用來DLL註冊和移除註冊
public static string BHOKEYNAME = @"SOFTWARE...Browser Helper Objects";
[ComRegisterFunction]
public static void RegisterBHO(Type type)
{
RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(BHO_KEY_NAME, true);
if (registryKey == null)
{
registryKey = Registry.LocalMachine.CreateSubKey(BHO_KEY_NAME);
}
string guid = type.GUID.ToString("B");
RegistryKey bhoKey = registryKey.OpenSubKey(guid, true);
if (bhoKey == null)
{
bhoKey = registryKey.CreateSubKey(guid);
}
// NoExplorer: dword = 1 prevents the BHO to be loaded by Explorer.exe
bhoKey.SetValue("NoExplorer", 1);
bhoKey.Close();
registryKey.Close();
}
[ComUnregisterFunction]
public static void UnregisterBHO(Type type)
{
RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(BHO_KEY_NAME, true);
string guid = type.GUID.ToString("B");
if (registryKey != null)
registryKey.DeleteSubKey(guid, false);
}
接下來就是實現具體的統計功能了。考慮一下,當輸入網址後,我們需要記錄下網址以及當前的時間;當在同一瀏覽視窗中切換網址時,不僅需要記錄下網址和目前時間,還要設定前一個瀏覽記錄的結束時間;並且在關閉瀏覽器時,也要記下結束時間。所以在SetSite中需要掛載NavigateComplete2和OnQuit事件。
private void NavigateComplete2(object pDisp, ref object URL)
{
string url = URL as string;
if (url.IndexOf("about:blank") >= 0)
{
return;
}
if (visitHists.Count > 0)
{
VisitHist currentHist = visitHists[visitHists.Count - 1];
if (currentHist.VisitUrl != url)
{
currentHist.EndTime = System.DateTime.Now;
}
else
{
return;
}
}
VisitHist newHist = new VisitHist();
newHist.StartTime = System.DateTime.Now;
newHist.VisitUrl = url;
visitHists.Add(newHist);
}
private void OnQuit()
{
if (visitHists.Count > 0)
{
VisitHist currentHist = visitHists[visitHists.Count - 1];
currentHist.EndTime = System.DateTime.Now;
}
// 輸出統計記錄
...
}
開始編譯,然後就可以在bin目錄下找到項目的dll檔案了。在Console中使用regasm /codebase "UrlTrack.dll"註冊dll。開啟註冊表,在HKLMSOFTWARE...Browser Helper Object可以看到多出了一個子項{E90DA13B-117A-4178-8111-0F712DA09FF9}。
需要注意的是,需要將AssemblyInfo.cs檔案中的ComVisible屬性設為true,否則在註冊BHO時會得到這樣的資訊:
RegAsm : warning RA0000 : No types were registered.
更多的BHO資料可以看這裡:Browser Extensions
[1] 在Windows作業系統上有兩種瀏覽器:資源總管(explorer.exe,應用於檔案系統)和Internet瀏覽器(IEXPLORE.EXE,應用於互連網資源)。
代碼下載