摘自:http://www.cnblogs.com/mvc2014/p/3776054.html
微軟在1997年正式推出Browser Helper Object (BHO), 使程序員能夠更好的對IE進行二次開發和操作. 在通過編寫BHO程序數月后, 我希望把我的一些經驗告訴才開始的同志, 避免走一些彎路.
我本人是非常喜歡C++的. 因為C++對內存直接操作的方式可以節省非常多的內存損耗, 也更快一些. 但是在開發BHO的時候, 我的確也認識到, C#明顯要比C++強大很多. 例如C#提供的FOREACH 循環就可以避免FOR循環產生的溢出. 另外C#的類型轉換也明顯要強于C++. 畢竟BHO和C#都是出自微軟一家, 理所當然, C#更適合BHO開發一些. 我的第一個BHO程序是用C++寫的. 對于COM的操作,讓我至少弄了幾天才搞清楚他們到底想干什么. 但是我的第一個C# BHO程序只用了幾分鐘就搭建好了鉤子. 如果你希望從事BHO開發, 而且你才開始學. 我想這篇文章對您有點幫助.
下面就讓我們開始.
首先我們需要在C#中新建一個DLL工程. 因為BHO是通過讓IE調用DLL來驅動的. 我用的是VC# EXPRESS. 因為這已經完全夠用了. VC# PROFESSIONAL 并不需要, 而且還很浪費內存.
當我們建立一個空工程以后, 隨便添加一個文件夾叫BHO, 然后添加一個文件.
需要我們注意的是, 我們這個文件必須被命名為IObjectWithSite.cs因為這樣IE才知道這是一個BHO程序. 如果想知道更多關于IObjectWiteSite接口的內容, 請查詢MSDN http://msdn2.microsoft.com/en-us/library/Aa768220.aspx
在IObjectWithSite中必須有兩個方法GetSite和SetSite. 我們主要是對后者進行調用.通過名字大家就可以猜到他們是干什么的.
GetSite: Gets the last site set with IObjectWithSite::SetSite. If there is no known site, the object returns a failure code.
SetSite: Provides the site's IUnknown pointer to the object.
請把VS STUIDO 默認的類名給去掉.因為IObjectWithSite并不是一個類, 而是一個接口.
不要忘記添加 System.Runtime.InteropServices
下面我們再添加劑一個叫BHO.CS的主文件.
這個新建的類是基于 IObjectWithSite接口的. 正如同我前面講的. 你就是通過這個接口來調用IE.
為了使用微軟的BHO庫.我們必須添加下面兩個庫: SHDocVw and MSHTML.他們一般都在 Windows\System32 下面
SHDocVw is Microsoft Shell Doc Object and Control Library
MSHTML is: All interfaces for accessing the Dynamic HTML (DHTML) Object Model are based on IDispatch and are the basis of access to the object model that is also used by scripts. http://msdn2.microsoft.com/en-us/library/bb498651.aspx
光using SHDocVw" 是不夠的, 你需要添加
Add SHDocVw
因為稍后我們需要用到MESSAGEBOX, 所以這里我也添加了一個WINDOWS FORM庫
下面添加兩個變量: WebBrowser and HTMLDocument. 就如同他們的名字. 一個是IE的變量, 另外一個是IE所訪問的HTML頁變量.
下面在這個類中田間一個叫 OnDocumentComplete 的函數. 取其他名字也行, 沒什么太大關系. 但是這里為了CODE的可用性,我們叫OnDocumentComplete. 這個函數實際上是和CDHTMLDIALO
下面的OnDocumentComplete所對應的.
CDHtmlDialog Class http://msdn2.microsoft.com/en-us/library/8bed8k60(VS.80).aspx .
OnDocumentComplete的觸發是在一個HTML頁被LOAD完以后. 你也可以避免用Navigate() or OnBeforeNavigate(). 他們表示在發出訪問和訪問之前觸發.
Please refer to http://msdn2.microsoft.com/en-us/library/8k5z3ekh(VS.80).aspx to find out what you need exactly.
在 IObjectWithSite.cs下,你需要找出IE的GUID, 這樣才方便注冊表的更改.
另外你需要給自己的程序添加一個GUID. 這樣IE才能在注冊表中找到你的信息. 你可以使用System.Guid.NewGuid() method 來得到一個GUID. 這比C++得到GUID的方法要容易得多了.
我們必須給 SetSite and GetSite 加上內容. 在SETSITE中我們就需要加入一個EVENTHANDLER, 讓IE來觸發我們的OnDocumentComplete函數.
添加引用
在BHO.CS下我們需要為我們的DLL添加register/unregister 函數.
編譯, 我們就有了我們的DLL.
下面通過DOS下的 regasm /codebase "BHO HelloWorld.dll" 命令在注冊dll. 這里有一個問題了, 為什么?
因為我們忘了把我們的主類設置成PUBLIC, 所以別人都不能調用到你的類. 自然注冊不了.
然后就成功了.
打開注冊表, 找到Browser Helper Object under LOCAL_MACHINE->SOFTWARE->MICROSOFT->WINDOWS->EXPLORER, 看看是不是有變化了?
我們注冊完了, 下面就是來寫我們的住程序來控制IE了. 下面就是一個例子來抓去你正訪問的頁面上的所有INPUT 元素的NAME.
在DOCUMENT中, 我們的所有元素都為IHTMLElement, 我們需要調用的是IHTMLInputElement. 所以我們通過GetElementByTagName的方法來查找所有的INPUT ELEMENT. 在找到以后還需要進行類型轉換才能找到對應的ATTRIBUTE. 否則IHTMLElement是不代有NAME ATTRIBUTE的. IHTMLElement提供的ATTRIBUTE都是所有元素都有的. 例如ID, 例如TITLE, 例如OnClick等. 有的元素有自己特有的ATTRIBUTE, 例如INPUT有OnFocus這就必須要轉換成IHTMLInputElement才能上使用. INPUT對應的IHTMLInputElement, Select-> IHTMLSelectElement .......
There you go, see?
下面我們試另外一個方法叫 BeforeNavigate() .它的觸發是在你開始下一個頁面之前. 也就是說例如你要提交一個表單, 頁面要變化了, 他就被觸發.
實際上MS提供了兩個類似的接口 BeforeNavigate and BeforeNavigate2(). 大家可以查MSDN看看有什么區別. 這里我們不多講了.
同樣我們添加一個對應的函數原形(點圖片, 看大圖).
添加EVENTHANDLER
我們下面要干的是截獲頁面上的密碼.
看,多簡單,你也能做到!
我希望您對BHO有一個初步的了解. 如果想知道更多內容, 請訪問MSDN. 里面有非常詳細的介紹. 這里也引出了一個話題. 我們可以看到, 幾乎用不了兩分鐘我們就可以截獲你填寫的任何內容, 你覺得IE是安全的嗎? 即使他可以通過SSL來對進出網卡的內容加密, 但是在應用層一樣是如此的薄弱. 另外大家如果用IE都會發覺泛濫成災的ADD-ON, 這就是因為BHO惹的禍.
大家如果不想按照我上面的打,可以下我做好的模版.直接放到你的Visual Studio 2005\Templates\ProjectTemplates文件夾下. 當開始一個新工程時候, 點下那個BHO HELLOWORLD就可以了. 所有上面的代碼都給你做好了.
文章列表