利用未公開函數實現Shell操作監視 |
|
axsoft
版主 發表:681 回覆:1056 積分:969 註冊:2002-03-13 發送簡訊給我 |
利用未公開函數實現Shell操作監視wwwa.applevb.com 在Windows下有一個未公開函數SHChangeNotifyRegister可以吧你的窗口添加到系統的系統消息監視鏈中,該函數在Delphi 中的定義如下: Function SHChangeNotifyRegister(hWnd,uFlags,dwEventID,uMSG,cItems:LongWord; lpps:PIDLSTRUCT):integer;stdcall;external 'Shell32.dll' index 2; 其中參數hWnd定義了監視系統操作的窗口得句柄,參數uFlags dwEventID定義監視操作參數,參數uMsg定義操作消息,參數cItems 定義附加參數,參數lpps指定一個PIDLSTRUCT結構,該結構指定監視的目錄。 當函數調用成功之后,函數會返回一個監視操作句柄,同時系統就會將hWnd指定的窗口加入到操作監視鏈中,當有文件操作發生 時,系統會向hWnd發送uMsg指定的消息,我們只要在程序中加入該消息的處理函數就可以實現對系統操作的監視了。 如果要退出程序監視,就要調用另外一個未公開得函數SHChangeNotifyDeregister來取消程序監視。 下面是使用Delphi編寫的具體程序實現範例,首先建立一個新的工程文件,然后在form1中加入一個Button控件和一個Memo控件, 程序的代碼如下:unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, forms, Dialogs, StdCtrls,shlobj,Activex; const SHCNE_RENAMEITEM = $1; SHCNE_CREATE = $2; SHCNE_DELETE = $4; SHCNE_MKDIR = $8; SHCNE_RMDIR = $10; SHCNE_MEDIAINSERTED = $20; SHCNE_MEDIAREMOVED = $40; SHCNE_DRIVEREMOVED = $80; SHCNE_DRIVEADD = $100; SHCNE_NETSHARE = $200; SHCNE_NETUNSHARE = $400; SHCNE_ATTRIBUTES = $800; SHCNE_UPDATEDIR = $1000; SHCNE_UPDATEITEM = $2000; SHCNE_SERVERDISCONNECT = $4000; SHCNE_UPDATEIMAGE = $8000; SHCNE_DRIVEADDGUI = $10000; SHCNE_RENAMEFOLDER = $20000; SHCNE_FREESPACE = $40000; SHCNE_ASSOCCHANGED = $8000000; SHCNE_DISKEVENTS = $2381F; SHCNE_GLOBALEVENTS = $C0581E0; SHCNE_ALLEVENTS = $7FFFFFFF; SHCNE_INTERRUPT = $80000000; SHCNF_IDLIST = 0; // LPITEMIDLIST SHCNF_PATHA = $1; // path name SHCNF_PRINTERA = $2; // printer friendly name SHCNF_DWORD = $3; // DWORD SHCNF_PATHW = $5; // path name SHCNF_PRINTERW = $6; // printer friendly name SHCNF_TYPE = $FF; SHCNF_FLUSH = $1000; SHCNF_FLUSHNOWAIT = $2000; SHCNF_PATH = SHCNF_PATHW; SHCNF_PRINTER = SHCNF_PRINTERW; WM_SHNOTIFY = $401; NOERROR = 0; type Tform1 = class(Tform) Button1: TButton; Memo1: TMemo; procedure formClose(Sender: TObject; var Action: TCloseAction); procedure Button1Click(Sender: TObject); procedure formCreate(Sender: TObject); private { Private declarations } procedure WMShellReg(var Message:TMessage);message WM_SHNOTIFY; public { Public declarations } end; type PSHNOTIFYSTRUCT=^SHNOTIFYSTRUCT; SHNOTIFYSTRUCT = record dwItem1 : PItemIDList; dwItem2 : PItemIDList; end; Type PSHFileInfoByte=^SHFileInfoByte; _SHFileInfoByte = record hIcon :Integer; iIcon :Integer; dwAttributes : Integer; szDisplayName : array [0..259] of char; szTypeName : array [0..79] of char; end; SHFileInfoByte=_SHFileInfoByte; Type PIDLSTRUCT = ^IDLSTRUCT; _IDLSTRUCT = record pidl : PItemIDList; bWatchSubFolders : Integer; end; IDLSTRUCT =_IDLSTRUCT; function SHNotify_Register(hWnd : Integer) : Bool; function SHNotify_UnRegister:Bool; function SHEventName(strPath1,strPath2:string;lParam:Integer):string; Function SHChangeNotifyDeregister(hNotify:integer):integer;stdcall; external 'Shell32.dll' index 4; Function SHChangeNotifyRegister(hWnd,uFlags,dwEventID,uMSG,cItems:LongWord; lpps:PIDLSTRUCT):integer;stdcall;external 'Shell32.dll' index 2; Function SHGetFileInfoPidl(pidl : PItemIDList; dwFileAttributes : Integer; psfib : PSHFILEINFOBYTE; cbFileInfo : Integer; uFlags : Integer):Integer;stdcall; external 'Shell32.dll' name 'SHGetFileInfoA'; var form1: Tform1; m_hSHNotify:Integer; m_pidlDesktop : PItemIDList; implementation {$R *.DFM} function SHEventName(strPath1,strPath2:string;lParam:Integer):string; var sEvent:String; begin case lParam of file://根據參數設置提示消息 SHCNE_RENAMEITEM: sEvent := '重命名文件' strPath1 '為' strpath2; SHCNE_CREATE: sEvent := '建立文件 文件名:' strPath1; SHCNE_DELETE: sEvent := '刪除文件 文件名:' strPath1; SHCNE_MKDIR: sEvent := '新建目錄 目錄名:' strPath1; SHCNE_RMDIR: sEvent := '刪除目錄 目錄名:' strPath1; SHCNE_MEDIAINSERTED: sEvent := strPath1 '中插入可移動存儲介質'; SHCNE_MEDIAREMOVED: sEvent := strPath1 '中移去可移動存儲介質' strPath1 ' ' strpath2; SHCNE_DRIVEREMOVED: sEvent := '移去驅動器' strPath1; SHCNE_DRIVEADD: sEvent := '添加驅動器' strPath1; SHCNE_NETSHARE: sEvent := '改變目錄' strPath1 '的共享屬性'; SHCNE_ATTRIBUTES: sEvent := '改變文件目錄屬性 文件名' strPath1; SHCNE_UPDATEDIR: sEvent := '更新目錄' strPath1; SHCNE_UPDATEITEM: sEvent := '更新文件 文件名:' strPath1; SHCNE_SERVERDISCONNECT: sEvent := '斷開與服務器的連接' strPath1 ' ' strpath2; SHCNE_UPDATEIMAGE: sEvent := 'SHCNE_UPDATEIMAGE'; SHCNE_DRIVEADDGUI: sEvent := 'SHCNE_DRIVEADDGUI'; SHCNE_RENAMEFOLDER: sEvent := '重命名文件夾' strPath1 '為' strpath2; SHCNE_FREESPACE: sEvent := '磁盤空間大小改變'; SHCNE_ASSOCCHANGED: sEvent := '改變文件關聯'; else sEvent:='未知操作' IntToStr(lParam); end; Result:=sEvent; end; function SHNotify_Register(hWnd : Integer) : Bool; var ps:PIDLSTRUCT; begin {$R-} Result:=False; If m_hSHNotify = 0 then begin file://獲取桌面文件夾的Pidl if SHGetSpecialFolderLocation(0, CSIDL_DESKTOP, m_pidlDesktop)<> NOERROR then form1.close; if Boolean(m_pidlDesktop) then begin ps.bWatchSubFolders := 1; ps.pidl := m_pidlDesktop; // 利用SHChangeNotifyRegister函數注冊系統消息處理 m_hSHNotify := SHChangeNotifyRegister(hWnd, (SHCNF_TYPE Or SHCNF_IDLIST), (SHCNE_ALLEVENTS Or SHCNE_INTERRUPT), WM_SHNOTIFY, 1, ps); Result := Boolean(m_hSHNotify); end Else // 如果出現錯誤就使用 CoTaskMemFree函數來釋放句柄 CoTaskMemFree(m_pidlDesktop); End; {$R } end; function SHNotify_UnRegister:Bool; begin Result:=False; If Boolean(m_hSHNotify) Then file://取消系統消息監視,同時釋放桌面的Pidl If Boolean(SHChangeNotifyDeregister(m_hSHNotify)) Then begin {$R-} m_hSHNotify := 0; CoTaskMemFree(m_pidlDesktop); Result := True; {$R-} End; end; procedure Tform1.WMShellReg(var Message:TMessage); file://系統消息處理函數 var strPath1,strPath2:String; charPath:array[0..259]of char; pidlItem:PSHNOTIFYSTRUCT; begin pidlItem:=PSHNOTIFYSTRUCT(Message.wParam); file://獲得系統消息相關得路徑 SHGetPathFromIDList(pidlItem.dwItem1,charPath); strPath1:=charPath; SHGetPathFromIDList(pidlItem.dwItem2,charPath); strPath2:=charPath; Memo1.Lines.Add(SHEvEntName(strPath1,strPath2,Message.lParam) chr(13) chr(10)); end; procedure Tform1.formClose(Sender: TObject; var Action: TCloseAction); begin file://在程序退出的同時刪除監視 if Boolean(m_pidlDesktop) then SHNotify_Unregister; end; procedure Tform1.Button1Click(Sender: TObject); file://Button1的Click消息 begin m_hSHNotify:=0; if SHNotify_Register(form1.Handle) then begin file://注冊Shell監視 ShowMessage('Shell監視程序成功注冊'); Button1.Enabled := False; end else ShowMessage('Shell監視程序注冊失敗'); end; procedure Tform1.formCreate(Sender: TObject); begin Button1.Caption := '打開監視'; end; end.運行程序,點擊“打開監視”按鈕,如果出現一個顯示“Shell監視程序成功注冊”的對話框,說明form1已經加入到系統操作監視鏈中了, 你可以試著在資源管理器中建立、刪除文件夾,移動文件等操作,你可以發現這些操作都被紀錄下來並顯示在文本框中。 在上面的程序中多次使用到了一個PItemIDList的結構,這個數據結構指定Windows下得一個“項目”,在Windows下資源實現統一管理 一個“項目”可以是一個文件或者一個文件夾,也可以是一個打印機等資源。另外一些API函數也涉及到了Shell(Windows外殼)操作,各位 讀者可以參考相應的參考資料。 網路志工聯盟----Visita網站http://www.vista.org.tw ---[ 發問前請先找找舊文章 ]--- 發表人 - axsoft 於 2002/08/16 16:25:46 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |