Delphi版COM高級應用

Delphi深度探索之外殼執行操作記錄器

作者: 哈巴狗的小窩來源:希賽網http://www.csai.cn2006年01月20日

記錄外殼的活動

記錄外殼活動有很多好處,比如當需要監控用戶的行爲,回溯系統崩潰前的過程。實現這一功能的關鍵工具相當簡單,它就是COM接口IShellExecuteHook。編寫一個實現了這一接口的COM對象後,再在系統中注冊,就可以容易地控制並影響Windows外殼的運行。Windows 98和Windows 2000都支持IShellExecuteHook外殼擴展,而在Windows 95和Windows NT 4.0上則必須安裝活動桌面擴展後才支持(也就是說必須安裝IE 4.01)。

一個實現了IShellExecuteHook接口的COM對象可以截獲所有對ShellExecute和ShellExecuteEx函數的調用。ShellExecute和ShellExecuteEx函數主要用于執行應用程序,它們可以接收一個文件名並能自動獲得同文件名相關的可執行文件名。此外,它們還支持系統安全認證。如果在NT上設定了用戶的可執行權限,ShellExecute和ShellExecuteEx函數將會在創建新的進程前檢查權限(CreateProcess和WinExec函數則沒有這項功能)。函數調用的流程如下:

(1)獲得將要運行的可執行文件名。

(2)根據程序名檢查用戶執行權限。

(3)激活全部已注冊的IshellExecuteHook擴展。

(4)當所有擴展和權限都同意執行,創建新的進程並返回。

Windows外殼大量調用ShellExecute和ShellExecuteEx函數來執行幾乎是所有的資源管理器的操作,比如雙擊目錄、浏覽文件夾內容、打印編輯文檔、查看文件屬性、選擇文檔的上下文相關菜單等等。此外,開始菜單的運行對話框和DOS方式下的Start.exe也使用ShellExecuteEx函數來執行程序。簡單地說幾乎用戶的所有外殼操作都可以被擴展截獲,包括其他應用程序對ShellExecute和ShellExecteEx的調用。

Delphi版COM高級應用

編寫外殼活動記錄器

首先需要創建一個進程內COM對象,選菜單命令New | ActiveX Library,然後點擊菜單New|Com Object,創建COM對象框架,按圖2.14填充對話框的內容,然後點擊OK按鈕。Delphi就會自動生成框架文件,並保存生成的文件。

IShellExecuteHook的接口定義在shlobj.pas單元中,添加shlobj到單元uses部分,然後添加IShellExecuteHooko方法原型到COM對象聲明部分,聲明部分代碼如下:

unit ShellExecuteHookObj;

interface

uses

Windows, ActiveX, ComObj, ShlObj, ShellAPI;

type

TTShellExecuteHook = class (TComObject, IShellExecuteHook)

protected

function Execute(var ShellExecuteInfo: TShellExecuteInfo): HResult; stdcall;

end;

const

Class_TShellExecuteHook: TGUID = '{935FA400-243D-11D3-B06E-857B2AE2BE64}';

下面就是用來截獲並記錄外殼操作的實現部分,一旦外殼擴展被注冊後,每次ShellExecute 和ShellExecuteEx函數運行時都會調用COM對象的Execute函數。我們的核心代碼就是通過Execute方法實現的。方法定義如下:

function TTShellExecuteHook.Execute(

var ShellExecuteInfo: TShellExecuteInfo): HResult;

Execute方法會從外殼獲得一個類型爲TshellExecuteInfo的參數,參數定義如下:

_SHELLEXECUTEINFOA = record

cbSize: DWORD;

fMask: ULONG;

Wnd: HWND;

lpVerb: PAnsiChar;

lpFile: PAnsiChar;

lpParameters: PAnsiChar;

lpDirectory: PAnsiChar;

nShow: Integer;

hInstApp: HINST;

{ Optional fields }

lpIDList: Pointer;

lpClass: PAnsiChar;

hkeyClass: HKEY;

dwHotKey: DWORD;

hIcon: THandle;

hProcess: THandle;

end;

這個記錄結構中的lpFile包含了要運行的文件名,而lpVerb則表明執行的動作,動作由一些標准的字符串代表,比如,open(打開)、print(打印)、edit(編輯)、explore(浏覽)、properties(屬性)、find(查找)和其他上下文菜單的命令名。 有時,lpFile並不包含可執行文件名,這是因爲ShellExecute接到的運行參數是一個文檔名。比如當我們在資源管理器中雙擊文本文件時,Windows用文本文件名作爲參數調用ShellExecute函數,而ShellExecute函數則獲得同文本文件相關聯的可執行文件名,然後執行。

TShellExecuteInfo結構中還記錄了要運行程序的很多信息,然而這裏我們只能在Execute方法中修改nCmdShow參數,nCmdShow參數定義了窗口在運行後的顯示狀態,包括最大化、最小化、正常等選項,對于其他參數的修改都會被外殼忽略。除此之外,在Execute方法中可以根據情況允許外殼繼續缺省的任務或通知外殼取消執行,這可以通過Execute函數的返回值來實現。

如果Execute的返回值爲S_FALSE,外殼就繼續缺省的任務,如果返回S_OK,則外殼認爲擴展已經成功,就不再繼續執行了。另外如果返回一個錯誤代碼或系統無法識別的值,則外殼會彈出錯誤信息。這給了我們一個控制程序運行的機會,比如可以限制任何對記事本的調用,代碼如下:

function TTShellExecuteHook.Execute(

var ShellExecuteInfo: TShellExecuteInfo): HResult;

var

FileName: String;

begin

Result := S_FALSE;

with ShellExecuteInfo do

begin

FileName := UpperCase(ExtractFileName(lpFile));

if Pos('NOTEPAD', FileName) = 1 then

begin

Result := S_OK;

hInstApp := 32;

MessageBox(Wnd, '不允許記事本運行!', '錯誤', MB_OK or MB_ICONERROR);

end;

end;

end;

進一步,我們甚至可以利用這點實現一個自定義的安全認證機制,根據用戶要求限制運行的程序。有興趣的朋友可以試驗一下,一定很有意思。

有一點要注意的是,在Execute方法下不能調用ShellExecute和ShellExecuteEx函數外部程序,如果是這樣的話,我們的Execute方法又會被新的ShellExecute調用,這樣系統就會進入死循環。如果我們確實想在Execute方法中調用外部程序的話,可以使用CreateProcess或WinExec函數來替代。這兩個函數不會被ShellExecuteHook截獲。

對于外殼動作記錄器來說,只要在Execute方法中記錄程序信息到日志文件中就可以了,代碼非常簡單,因爲所有需要的信息都在TShellExecuteInfo記錄中包含了,這裏只記錄運行的動作、文件名和時間,需要記錄其他信息的話,大家可自行修改,代碼示意如下:

function TTShellExecuteHook.Execute(

var ShellExecuteInfo: TShellExecuteInfo): HResult;

var

FileStream: TFileStream;

a:TStringList;

S:string;

begin

Result := S_FALSE;

with ShellExecuteInfo do

begin

FileStream:=TFileStream.Create('c:\shellexecutehook.txt',fmopenwrite);

S:=string(lpVerb)+':'+string(lpFile)+DateTimeToStr(Now)+#13#10;

FileStream.Seek(FileStream.Size,soFromBeginning);

FileStream.Write(PChar(S)^,Length(S));

FileStream.Free;

end;

end;

注冊ShellExecuteHook

要想使COM對象被外殼加載,需要在注冊表中注冊一些信息。在下面這個子鍵中添加COM類的GUID及描述字符串後就可以了(描述字符串可以不賦值,但不妨給一個以便于識別)。

HKEY_LOCAL_MACHINE

SOFTWARE

Microsoft

Windows

CurrentVersion

Explorer

ShellExecuteHooks

{CLSID}= '描述字符串'

修改注冊表可以通過重載COM的類工廠的UpdateRegistry方法來實現。代碼示意如下:

implementation

uses ComServ, SysUtils;

resourcestring

sCreateRegKeyError = '創建注冊表項失敗';

type

TShellExComObjectFactory = class(TComObjectFactory)

public

procedure UpdateRegistry(Register: Boolean); override;

end;

{ TShellExComObjectFactory }

procedure TShellExComObjectFactory.UpdateRegistry(Register: Boolean);

const

hellExecuteHooksKey='

SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellExecuteHooks';

var

Handle: HKey;

Status, Disposition: Integer;

ClassID: String;

begin

ClassID := GUIDToString(Class_TShellExecuteHook);

if Register then

begin

Status := RegCreateKeyEx(HKEY_LOCAL_MACHINE, PChar(

ShellExecuteHooksKey), 0, '',REG_OPTION_NON_VOLATILE,

KEY_READ or KEY_WRITE, nil, Handle, @Disposition);

if Status = 0 then

begin

Status := RegSetValueEx(Handle, PChar(ClassID), 0, REG_SZ,

PChar(Description), Length(Description) + 1);

RegCloseKey(Handle);

end;

end else

begin

Status := RegOpenKeyEx(HKEY_LOCAL_MACHINE, PChar(ShellExecuteHooksKey), 0,

KEY_READ or KEY_WRITE, Handle);

if Status = 0 then

begin

Status := RegDeleteValue(Handle, PChar(ClassID));

RegCloseKey(Handle);

end;

end;

if Status <> 0 then raise EOleError.Create(sCreateRegKeyError);

inherited UpdateRegistry(Register);

end;

initialization

TShellExComObjectFactory.Create(

ComServer, TTShellExecuteHook, Class_TShellExecuteHook,'TShellExecuteHook',

'ShellExecute hook sample', ciMultiInstance, tmApartment);

end.

如果系統中有多個ShellExecuteHook的話,外殼會按照ShellExecuteHook的安裝順序進行調用,如果要想使某個外殼擴展優先運行,可先刪除其他擴展然後添加優先擴展,原來的擴展依次放在後面,不過這樣做也可能意義不大,因爲別人也會這麽幹。最後,程序運行的結果。

Delphi版COM高級應用

記住ShellExecuteHook並不是一個完善的用于監視系統運行的擴展。它只能監視ShellExecute和ShellExecuteEx的運行,它不能保證記錄系統所有的行爲。特別是很多情況下外殼並不使用ShellExecute來進行一些常用的操作,比如我們在資源管理器中選擇一個文件,然後調用右鍵菜單的屬性命令後,記錄器沒有記錄這個動作,但如果直接調用ShellExecute(如下示)的話,ShellExecuteHook卻會正確執行。

ShellExecute(nil, 'properties', 'foo.txt',nil,nil,SW_SHOW);

這說明外殼並不使用ShellExecute函數顯示屬性對話框。總之一定要謹慎使用這項技術,確保它確實符合工作的需求。

Delphi深度探索之自動完成外殼擴展

作者: 哈巴狗的小窩來源:希賽網http://www.csai.cn2006年01月20日

自動完成簡介

Delphi版COM高級應用

大家一定都非常熟悉IE浏覽器的地址輸入編輯框,它提供了自動完成的功能。自動完成(Auto Complete)功能簡化了編輯框的輸入功能,它可以根據已經輸入的部分字符串進行預測和匹配。圖2.7的例子,演示了自動完成可以依據輸入的“pro”,給出Pascal的保留字中與其相匹配的字符串列表"procedure"、"program"、"property"。

在利用自動完成功能前,必須要知道自動完成並不是任意版本的Windows都支持,自動完成功能實際上是由Internet Explorer 4.0引入並必須有4.71版及以上的Shell32.dll的支持。很多早期的系統,包括很多安裝了IE 4的系統並不支持這項特性,所以使用自動完成功能時必須確保要安裝的系統支持這項功能,如果不支持就需要安裝IE和集成外殼。

自動完成功能是通過一組COM接口來實現的。這些接口使我們可以連接自動完成到編輯框,添加編輯框可以枚舉的字符串列表並配置其顯示屬性。

1. 自動完成的用途

使用自動完成功能可以增強程序的易用性,它可以節省用戶反複輸入一些常用字符串的時間,並減少輸入錯誤。它還可以用于部分字符匹配的查找系統,可以用它實現對數據庫內容的快速查找。另外,它還支持向浏覽器曆史、最近運行程序和外殼目錄輸入等功能中添加自定義的完成列表。

2. 配置自動完成

需要知道的是在Delphi裏並沒有提供自動完成功能相關COM接口的pascal聲明單元。由于一般這類接口在微軟都是以C語言的頭文件形式提供接口,Delphi不可能及時提供最新的相應的Pascal包裝單元。所以爲了使用這項功能,本文中額外提供了一個shlintf單元翻譯了相應的頭文件的聲明。下表總結了Shlintf的內容:

COM對象

接 口

CLSID_AutoComplete

IAutoComplete

CLSID_ACLHistory

IAutoComplete2

CLSID_ACListISF

IACList

CLSID_ACLMRU

IACList2

CLSID_ACLMulti

ICurrentWorkingDirectory

IObjMgr

自動完成功能最基本的一個接口就是IAutoComplete接口,它的聲明如下:

type

IAutoComplete = interface(IUnknown)

[SID_IAutoComplete]

function Init(hwndEdit: HWND; punkACL: IUnknown; pwszRegKeyPath: PWideChar;

pwszQuickComplete: PWideChar): HResult; stdcall;

function Enable(fEnable: Boolean): HResult; stdcall;

end;

IautoComplete接口有兩個方法:Init和Enable。

Init方法用來把IAutoComple接口以及自動完成列表同編輯框相連接。參數pwszRegKeyPath和pwszQuickComplete使得IAutoComplete接口可以按預定義的格式擴展部分輸入的字符串,快捷鍵爲CTRL+ENTER。比如設定pwszQuickComplete爲”http://www.%s.cn/”後,當用戶輸入"csai" 到編輯框,並按下快捷鍵CTRL+ENTER,編輯框中的文本就會更新爲http://www.csai.cn/。

Enable方法是根據fEnable標識來切換自動完成功能的開關狀態的。缺省時是激活的。

下圖顯示了IAutoComplete接口是如何自動完成字符串的,當用戶在編輯框中輸入字符時,一種可能是最能匹配已經輸入字符串的候選字符會被反白顯示。

Delphi版COM高級應用

回過頭再來看看Init方法的punkACL參數,它是一個必須的參數而且必須指向一個提供字符串的接口。注意不是我們熟悉的Delphi中提供的TStrings對象,而是一個IEnumString字符串接口。IEnumString接口負責生成一個用于自動完成的候選字符串列表。除了IEnumString接口外,punkACL參數還可以是IACList和IACList2等其他接口。

IACList接口簡單地說就是可以對候選字符串分類來改善自動完成的效率,本文中將不加介紹。

要注意的是Microsoft並沒有停止對自動完成功能的改進,在Internet Explorer 5.0中,Microsoft 還提供了IAutoComplete2接口。IAutoComplete2接口進行了進一步的擴展,它使得我們可以設定一系列的選項來設定自動完成的可視化表達以及操作。下面是 IAutoComplete2接口的聲明:

type

IAutoComplete2 = interface(IAutoComplete)

[SID_IAutoComplete2]

function SetOptions(dwFlag: DWORD): HResult; stdcall;

function GetOptions(out dwFlag: DWORD):HResult; stdcall;

end;

IAutoComplete2接口引入了兩種新的方法,這兩種方法使用同樣的標識組合作爲參數,下表列出了可用的標識及其意義。

標 識

說 明

ACO_NONE

不使用自動完成

ACO_AUTOSUGGEST

使用下拉列表

ACO_AUTOAPPEND

允許自動附加在init方法中pwszQuickComplete參數所代表的字符串

ACO_SEARCH

在下拉列表最後添加"查找"文本

ACO_FILTERPREFIXES

防止自動完成匹配常用前綴比如"www.", "http://"等

ACO_USETAB

TAB鍵可以用來選擇下拉列表項

ACF_UPDOWNKEYDROPSLIST

上下按鍵可以用來調出下拉列表框

ACO_RTLREADING

按由右到左的順序讀

就像下圖所顯示的那樣,IAutoComplete2同IAutoComplete的顯示方式有一點不同,就是因爲IAutoComplete2支持不同的顯示模式,這些模式可以通過SetOptions 方法來設定。

Delphi版COM高級應用

3. 實現自動完成

自動完成功能是通過COM對象來實現的,下面代碼用As操作符來獲得IAutoComplete2接口:

FAutoComplete :=

CreateComObject(CLSID_AutoComplete) as IAutoComplete2;

獲得接口後我們就可以實現自動完成功能了,下面代碼是一個簡單的例子:

unit Main;

interface

uses

Windows, Messages, SysUtils, Classes, Graphics,

Controls, Forms, Dialogs, ShlIntf, ActiveX,

ComObj, StdCtrls, StrTools;

type

TAutoCompleteForm = class(TForm)

CompletionEdit: TEdit;

CompletionLabel: TLabel;

SourceGroupBox: TGroupBox;

SourceMemo: TMemo;

procedure FormCreate(Sender: TObject);

private

FAutoComplete: IAutoComplete2;

FStrings: IUnknown;

end;

var

AutoCompleteForm: TAutoCompleteForm;

implementation

{$R *.DFM}

{ TAutoCompleteForm }

procedure TAutoCompleteForm.FormCreate(Sender: TObject);

begin

FAutoComplete := CreateComObject(CLSID_AutoComplete) as IAutoComplete2;

FStrings := TEnumString.Create(SourceMemo.Lines) as IUnknown;

OleCheck(FAutoComplete.SetOptions(ACO_AUTOSUGGESTor ACO_UPDOWNKEYDROPSLIST));

OleCheck(FAutoComplete.Init(CompletionEdit.Handle, FStrings, nil, nil));

end;

end.

上面的例程首先獲得IAutoComplete2接口,如果系統不支持IAutoComplete2接口,as操作符將引發EinvalidCastError異常。接下來的一行代碼會創建一個TEnumString類的實例並取得IUnknown接口,這個接口將作爲FAutoComplete的Init方法的punkACL參數,TEnumString類是從TInterfacedObject類繼承的,實現在StrTools單元中,實現它的目的是使TStrings類同IEnumString接口兼容。然後,設定顯示選項使自動完成支持下拉列表和自動建議。最後初始化FAutoComplete並同編輯框相連接,被連接的編輯框就支持自動完成了。

4. 標准自動完成列表

除了支持標准的編輯框的自動完成,Microsoft還允許通過下表中的一組COM對象來存取標准自動完成列表。

COM對象

說 明

CLSID_History

允許存取曆史列表項

CLSID_ACListISF

允許操作外殼命名空間的內容

CLSID_MRU

提供最近運行過的程序列表

上面列出的COM對象提供了一個IUnknown接口,接口可以作爲IAutoComplete接口的Init方法的punkACL參數。每個IUnknown接口都支持IEnumString和IACList接口,同時還支持其他特殊接口。比如,外殼空間的IUnknown接口還公開了ICurrentWorkingDirectory和IPersistFolder接口。使用這些對象可以根據外殼空間的變化動態地改變候選字符串列表。

ICurrentWorkingDirectory和IPersistFolder接口的區別在于IPersistFolder使用item lists 而不是字符串。Item lists 便于存取虛擬文件夾比如控制面板。

下面的代碼演示了如何使用自動完成功能來設定C:\下的外殼內容爲候選字符串列表:

var

WorkingDirectory: ICurrentWorkingDirectory;

begin

FAutoComplete := CreateComObject(CLSID_AutoComplete) as IAutoComplete2;

FStrings := CreateComObject(CLSID_ACListISF);

WorkingDirectory := FStrings as ICurrentWorkingDirectory;

OleCheck(WorkingDirectory.SetDirectory('C:\'));

OleCheck(FAutoComplete.SetOptions(ACO_AUTOSUGGEST or ACO_UPDOWNKEYDROPSLIST));

OleCheck(FAutoComplete.Init(CompletionEdit.Handle, FStrings, nil, nil));

end;

5. 改進自動完成

雖然自動完成功能實現起來很簡單,但爲了更好在Delphi中使VCL框架一致,應該創建對它的VCL封裝。另外的改進應該是要提供對其他嵌入編輯框的控件的自動完成功能的實現。如下圖,TAutoComplete組件被連接到了一個TtreeView控件上。

Delphi版COM高級應用

總的來說,自動完成功能是一項非常棒的功能,它可以簡化用戶同經常輸入的文本交互的過程。用好自動完成功能,會使得你的程序顯得很專業。

Delphi開發嵌入式IE浏覽器監控程序

作者:佚名來源:希賽網http://www.csai.cn2006年02月05日

引言

隨著網絡的發展和普及,對網絡的監控日益成爲網絡安全的必然要求,也是管理和維護網絡的一個有效手段。當前已經有多種應用比較廣泛的網絡監控和過濾程序,如美萍網管、we-blocker等,它們都可以實現基于網絡URL和IP地址的監控和過濾功能。

本文將對如何開發一個嵌入到IE浏覽器中的監控程序進行介紹,該程序可以根據網絡URL和IP地址進行監控和過濾,並且記錄系統日志,從而使你對IE(當然是使用它的用戶)的所有操作一覽無余。相信通過閱讀本文,會加深你對網絡監控程序的理解,以及提高你的COM編程能力和數據庫編程能力。

本文在Delphi 6開發環境下實現,數據庫使用桌面數據庫Access 2000。

基礎知識

1.COM編程

COM(Component Object Model,組建對象模型)是微軟公司(Microsoft Company)提出的二進制通信規範,用于軟件組件之間的跨越多個進程、機器、硬件和操作系統的互操作,它是一項通過接口(Interface)透明的傳遞封裝數據的技術,並且獨立于語言和操作平台。一個COM對象是實現一個或者若幹個接口的對象,即COM對象借助接口輸出它所提供的服務。

2.IE浏覽器的體系結構

IE浏覽器的體系結構如圖1所示。其中MSHTML是位于SHDOCVW和HTML頁面之間的COM對象,SHDOCVW對象用于處理頁面的顯示,而MSHTML用于處理頁面的語法分析,並且將頁面中的標記轉換爲元素。MSHTML是一個COM服務器,允許COM客戶端程序訪問它對外提供的服務。

實現IE浏覽器嵌入式編程的基本方法是建立COM對象,從而以COM客戶端程序的形式和MSHTML COM服務器建立連接,然後通過接口回調實現需要的控制功能。也即首先建立COM對象,實現系統規定的若幹接口,然後注冊COM對象,並且將COM對象的有關信息寫入到IE浏覽器擴展功能指定的注冊表位置。

Delphi版COM高級應用

嵌入式IE浏覽器監控程序的實現

嵌入式IE浏覽器監控程序的實現主要包括監控程序的實現和維護程序的實現兩部分,根據程序開發過程,可以將其分爲四個步驟,下面分別對各個實現步驟進行詳細介紹。

1.實現COM對象

開發COM對象的任務就是建立一個能夠與IE浏覽器的MSHTML COM服務器建立連接並且通過接口回調實現控制功能的COM對象,具體實現過程如下:

(1)運行Delphi,依次點擊File|New|Other,切換到ActiveX頁面,選擇ActiveX Library,點擊OK按鈕,即建立一個新的工程。

(2) 再次點擊File|New|Other,切換到ActiveX頁面,選擇COM Object,點擊OK按鈕,即出現如圖2所示的COM Object Wizard界面,去掉Included Type Library複選框,在Class Name中輸入COM對象的名稱IEMonitor,然後點擊OK按鈕,即新建了一個名稱爲TIEMonitor的COM對象(該COM對象的CLSID由系統自動生成)(見圖2)。

Delphi版COM高級應用

(3)將工程和單元文件依次保存爲DIEMonitor.dpr和UIEMonitor.pas。切換到UIEMonitor.pas單元文件,編輯TIEMonitor的定義形式如下:

TIEMonitor = class(TComObject, IDispatch, IObjectWithSite)

public

functionGetTypeInfoCount(out Count:Integer):HResult;stdcall;

function GetTypeInfo(Index,LocaleID:Integer;out TypeInfo):HResult;stdcall;

function GetIDsOfNames(const IID:TGUID;Names:Pointer;

NameCount,LocaleID:Integer;DispIDs:Pointer):HResult;stdcall;

function SetSite(const pUnkSite:IUnknown):HResult;stdcall;

function GetSite(const riid:TIID;out site:IUnknown):HResult;stdcall;

function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;

Flags: Word; varParams; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;

private

IEThis:IWebBrowser2;

Cookie:Integer;

protected

end;

注意在UIEMonitor.pas單元文件的Uses中需要手動加入對SHDOCVW, Dialogs, SysUtils, Forms的引用。

其中主要是對IObjectWithSite接口的SetSite()方法和IDispatch接口的Invoke()方法的實現:首先通過SetSite()方法獲得IE的WebBrowser接口,然後尋找連接點,並且通過調用Advise()方法建立COM自身與連接點的連接;當連接建立成功後,IE在事件引發後,會調用連接到自身的IDispatch接口對象的Invoke方法,不同的事件對應不同的DispID編碼,因此可以通過在程序中判斷DispID對不同的事件做出相應的處理。系統主要對BeforeNavigate2、DownLoadComplete和OnQuit三個事件進行處理,它們對應的DispID分別爲250、104和253。在Invoke()方法中,根據DispID分別調用DoBeforeNavigate2()、DoDownLoadComplete()和DoOnQuit()函數實現相關處理和控制功能,具體實現詳見程序源代碼。

(4)編譯工程,生成DIEMonitor.dll文件。

2.注冊/卸載COM對象

注冊COM對象包括注冊COM對象,以及將COM對象的有關信息寫入到IE浏覽器擴展功能指定的注冊表位置,下面分別對其注冊方法進行介紹。卸載方法分別和注冊方法相對應。

(1)注冊/卸載COM對象。一種方法是在Delphi開發環境下運行Run|Register ActiveX Server/Run|Unregister ActiveX Server自動完成COM對象的注冊/卸載;另一種方法是通過調用MS Windows操作系統提供的regsvr32.exe命令進行注冊。

(2) 注冊/卸載COM對象的有關信息到IE浏覽器擴展功能指定的注冊表位置。將COM對象的CLSID寫入到IE浏覽器擴展功能指定的注冊表位置後,當IE浏覽器啓動時,就通過該CLSID查找COM對象有關信息(如文件路徑),從而實現了COM對象嵌入式功能擴展。爲了實現這個目的,只需要在注冊表的[HKEY_LOCAL_MACHINE\Software\Microsoft\ Windows\CurrentVersion\Explorer\Browser Helper Objects]項下,建立一個名稱爲COM對象的CLSID的注冊表項目即可。

3.開發監控模塊

監控模塊主要完成對IE浏覽器的監控功能,在Invoke()函數中觸發BeforeNavigator2事件時調用執行,主要包括ChkUrl()、WriteSite()、WriteLog()和GetIP()四個功能函數,分別完成檢查URL(及IP地址)、記錄URL和IP地址、記錄系統日志、根據URL取得IP地址的功能,分別簡單介紹如下,具體實現詳見程序源代碼。

(1)ChkUrl()函數:它是監控模塊的核心函數,也是模塊的入口函數。ChkUrl()函數首先取得用戶請求的URL,並且調用GetIP()函數取得其對應的IP地址,然後到系統中查找該URL及IP是否已經存在,如果存在則根據系統保存的結果禁止/允許用戶訪問,否則就根據系統的當前工作狀態(禁止/允許)動態處理,同時調用WriteSite()函數將該URL和IP地址保存到系統中。最後調用WriteLog()函數記錄系統日志。

(2)WriteSite()函數:完成將URL和IP地址保存到系統中的功能,同時記錄系統當前日期和時間。

(3)WriteLog()函數:將有關信息形成系統日志並且保存下來,主要有網絡URL和IP地址、用戶名稱、訪問日期和時間、處理結果(禁止/允許訪問)等信息。

(4)GetIP()函數:提供根據URL取得對應IP地址的功能,通過調用TNMHTTP組件的相關功能實現:首先將URL賦值給TNMHTTP組件的Host屬性,然後調用ResolveRemoteHost()方法,就可以從其RemoteIP屬性中獲得對應的IP地址。

4.開發維護程序

維護程序主要實現系統參數維護和日志管理兩方面功能,在啓動時需要管理員登錄。

(1)系統參數維護:啓用/停止系統監控功能等,程序界面如圖3所示。

Delphi版COM高級應用

(2)系統日志管理:日志的查詢、打印等功能(見圖4)。

Delphi版COM高級應用

總結和系統進一步完善計劃

本文詳細介紹了嵌入式IE浏覽器監控程序的開發方法和實現過程,該系統以COM對象的形式嵌入到IE浏覽器中,可以實現對IE浏覽器(即用戶)的監控功能。

 
DELPHI病案管理系統源代碼免費開放www.NewSureSoftt.com下載
DELPHI病案管理系統源代碼免費開放www.NewSureSoftt.com下載...查看完整版>>DELPHI病案管理系統源代碼免費開放www.NewSureSoftt.com下載
 
Delphi下的COM編程
Delphi下的COM編程作者:岑心 03/9(轉載需征得作者同意)Delphi通過向導可以非常迅速和方便的直接建立實現COM對象的代碼,但是整個COM實現的過程被完全的封裝,甚至沒有VCL那麽結構清晰可見。一個沒有C++下COM開發經...查看完整版>>Delphi下的COM編程
 
FastReport問題集 選自Delphi園地 http://www.delphifans.com/InfoView/Article_401.html
---------------- 使用自定義函數 ----------------------------------------Q: 我怎樣添加我的自定義函數?A: 使用 TfrReport.OnUserFunction 事件. 這裏有一個簡單的例子:procedure TForm1.frReport1UserFunction(c...查看完整版>>FastReport問題集 選自Delphi園地 http://www.delphifans.com/InfoView/Article_401.html
 
Delphi中COM 實現研究手記(一)
前些日子用 Delphi 寫了一個 Windows 外殼擴展程序,大家知道 Windows 外殼擴展實際上就是 COM 的一種應用 -- Shell COM,雖然整個程序寫得還算比較順利,但寫完後還是感覺對 Delphi 中 COM 的實現有點霧裏看花的感覺...查看完整版>>Delphi中COM 實現研究手記(一)
 
delphi編寫你的第一個com程序
delphi編寫你的第一個com程序
DELPHI菜單:File\New\Other…按確定按鈕點擊File\Save菜單保存:輸入工程名MyCOM按保存按鈕再打開菜單File\New\Other… 按[OK}按鈕;在CoClassName打入MyObject按OK在IMyObject上按MOUSE右鍵ImyObject\New\Method在Nam...查看完整版>>delphi編寫你的第一個com程序