線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:2009
推到 Plurk!
推到 Facebook!

Shell監視

 
jackkcg
站務副站長


發表:891
回覆:1050
積分:848
註冊:2002-03-23

發送簡訊給我
#1 引用回覆 回覆 發表時間:2002-10-26 02:55:44 IP:210.65.xxx.xxx 未訂閱
此為轉貼資料 Shell監視 作 者 :technofantasy 是否想?你的Windows加上一個眼睛,察看使用者在機器上所做的各種操作(例如建立、刪除文件;改變文件或目錄名字)呢?這裏介紹一種利用Windows未公開函數實現這個功能的方法。在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 //根據參數設置提示消息 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 //獲取桌面文件夾的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 //取消系統消息監視,同時釋放桌面的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); //系統消息處理 函數 var strPath1,strPath2:String; charPath:array[0..259]of char; pidlItem:PSHNOTIFYSTRUCT; begin pidlItem:=PSHNOTIFYSTRUCT(Message.wParam); //獲得系統消息相關得路徑 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 //在程式退出的同時刪除監視 if Boolean(m_pidlDesktop) then SHNotify_Unregister; end; procedure TForm1.Button1Click(Sender: TObject); //Button1的Click消息 begin m_hSHNotify:=0; if SHNotify_Register(Form1.Handle) then begin //註冊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外殼)操作,各位讀者可以參考相應的參考資料。 發表人 - JACKKCG 於 2002/10/26 03:02:11
------
**********************************************************
哈哈&兵燹
最會的2大絕招 這個不會與那個也不會 哈哈哈 粉好

Delphi K.Top的K.Top分兩個字解釋Top代表尖端的意思,希望本討論區能提供Delphi的尖端新知
K.表Knowlege 知識,就是本站的標語:Open our mind
系統時間:2024-04-27 9:14:49
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!