delphi 监控文件系统
elphi 监控文件系统 你是否想为你的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, Variants, Classes, Graphics, Controls, Forms,
Dialogs ,shlobj,Activex, StdCtrls; const
SHCNE_RENAMEITEM = $;
SHCNE_CREATE = $;
SHCNE_DELETE = $;
SHCNE_MKDIR = $;
SHCNE_RMDIR = $;
SHCNE_MEDIAINSERTED = $;
SHCNE_MEDIAREMOVED = $;
SHCNE_DRIVEREMOVED = $;
SHCNE_DRIVEADD = $;
SHCNE_NETSHARE = $;
SHCNE_NETUNSHARE = $;
SHCNE_ATTRIBUTES = $;
SHCNE_UPDATEDIR = $;
SHCNE_UPDATEITEM = $;
SHCNE_SERVERDISCONNECT = $;
SHCNE_UPDATEIMAGE = $;
SHCNE_DRIVEADDGUI = $;
SHCNE_RENAMEFOLDER = $;
SHCNE_FREESPACE = $;
SHCNE_ASSOCCHANGED = $;
SHCNE_DISKEVENTS = $2381F;
SHCNE_GLOBALEVENTS = $C0581E0;
SHCNE_ALLEVENTS = $7FFFFFFF;
SHCNE_INTERRUPT = $;
SHCNF_IDLIST = ;
// LPITEMIDLIST
SHCNF_PATHA = $;
// path name
SHCNF_PRINTERA = $;
// printer friendly name
SHCNF_DWORD = $;
// DWORD
SHCNF_PATHW = $;
// path name
SHCNF_PRINTERW = $;
// printer friendly name
SHCNF_TYPE = $FF;
SHCNF_FLUSH = $;
SHCNF_FLUSHNOWAIT = $;
SHCNF_PATH = SHCNF_PATHW;
SHCNF_PRINTER = SHCNF_PRINTERW;
WM_SHNOTIFY = $;
NOERROR = ; type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
procedure WMShellReg(var Message:TMessage);message WM_SHNOTIFY; { 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 [..] of char;
szTypeName : array [..] 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 ;
Function SHChangeNotifyRegister(hWnd,uFlags,dwEventID,uMSG,cItems:LongWord;lpps:PIDLSTRUCT):integer;stdcall;external 'Shell32.dll' index ;
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} { TForm1 } 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 = then begin
//获取桌面文件夹的pidl
if shgetspecialfolderlocation(, CSIDL_DESKTOP, m_pidldesktop) <> noerror then
form1.close;
if boolean(m_pidldesktop) then begin
new(ps);
try
ps.bwatchsubfolders := ;
ps.pidl := m_pidldesktop; // 利用shchangenotifyregister函数注册系统消息处理
m_hshnotify := shchangenotifyregister(hwnd, (shcnf_type or shcnf_idlist),
(shcne_allevents or shcne_interrupt),
wm_shnotify, , ps);
result := boolean(m_hshnotify);
finally
FreeMem(ps);
end;
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 := ;
CoTaskMemFree(m_pidlDesktop);
Result := True;
{$R-}
End;
end; procedure TForm1.WMShellReg(var Message: TMessage);
//file://系统消息处理函数
var
strPath1,strPath2:String;
charPath:array[..]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()+chr());
end; procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
//在程序退出的同时删除监视
if Boolean(m_pidlDesktop) then
SHNotify_Unregister;
end; procedure TForm1.Button1Click(Sender: TObject);
begin
m_hSHNotify:=;
if SHNotify_Register(Form1.Handle) then begin //file://注册Shell监视
ShowMessage('Shell监视程序成功注册');
Button1.Enabled := False;
end
else
ShowMessage('Shell监视程序注册失败');
end; end.
运行程序,点击“打开监视”按钮,如果出现一个显示“Shell监视程序成功注册”的对话框,说明Form1已经加入到系统操作监视链中了,你可以试着在资源管理器中建立、删除文件夹,移动文件等操作,你可以发现这些操作都被记录下来并显示在文本框中。
在上面的程序中多次使用到了一个PItemIDList的结构,这个数据结构指定Windows下得一个“项目”,在Windows下资源实现统一管理一个“项目”可以是一个文件或者一个文件夹,也可以是一个打印机等资源。另外一些API函数也涉及到了Shell(Windows外壳)操作,各位读者可以参考相应的参考资料。
由于使用到了Windows的未公开函数,没有相关得参考资料,所以有一些未知得操作(在Memo1中会显示“未知操作”)。如果哪位读者有兴趣, http://member.netease.com/~blackcat 有实现该功能的VB程序下载。
以上程序在Windows98、Windows2000、Delphi5下运行通过。
如果需要检测某个文件夹,可使用以下方法:
function TDyjPlatDirMonitor.RegisterDirMonitor(hWnd: Integer;
aPath: string): Boolean;
var
_vP : PWideChar;
_vPs : IDLSTRUCT;
begin
{$R-}
Result := False;
if FSHNotify = then
begin
_vP := PWideChar(WideString(aPath));
FPathPidl := SHSimpleIDListFromPath(_vP);
if Boolean(FPathPidl) then
begin
_vPs.bWatchSubFolders := ;
_vPs.pidl := FPathPidl;
FSHNotify := SHChangeNotifyRegister(hWnd,
(SHCNF_TYPE or SHCNF_IDLIST),
(SHCNE_ALLEVENTS or SHCNE_INTERRUPT),
WM_SHNOTIFY, , @_vPs);
Result := Boolean(FSHNotify);
end
else
CoTaskMemFree(FPathPidl);
end;
{$R+ }
end;
delphi 监控文件系统的更多相关文章
- 【AMAD】watchdog -- 用于监控文件系统的事件,并且提供了shell命令行工具
简介 动机 作用 用法 个人评分 简介 用于监控文件系统的事件的Python库,并且提供了shell命令行工具 动机 有很多情况下,我们希望监控文件的变化,在变化之后作出一些响应. 比如flask,d ...
- IO异步,读写压缩文件,监控文件系统
这节结尾IO,讲一下异步操作文件,读写压缩文件,监控文件系统这三个知识点. 异步操作文件: 说到异步,必然要了解的是async和await这两个关键字(异步详情点击基于任务的异步编程(Task ...
- delphi监控文件夹
(****************************************** 文件和目录监控 当磁盘上有文件或目录操作时,产生事件 使用方法: 开始监控: PathWatch(Self.Ha ...
- 使用pyinotify监控文件系统的变化
pyinotify依赖Linux内核inotify功能,它需要在2.6.13版本的内核的Linux系统上运行. 1. 安装pyinotify pip install pyinotify 安装完后可以直 ...
- inotify 监控文件系统操作
path0=path1=########################################################dir2watch1=/home/nanjing2/GridON ...
- linux inotify 监控文件系统事件
https://blog.csdn.net/cheng_fangang/article/details/41075515
- delphi 文件夹操作(监控)
delphi 监控文件系统 delphi 监控文件系统 你是否想为你的Windows加上一双眼睛,察看使用者在机器上所做的各种操作(例如建立.删除文件:改变文件或目录名字)呢? 这里介绍一种利用Win ...
- Inotify: 高效、实时的Linux文件系统事件监控框架
Inotify: 高效.实时的Linux文件系统事件监控框架 概要 - 为什么需要监控文件系统? 在日常工作中,人们往往需要知道在某些文件(夹)上都有那些变化,比如: 通知配置文件的改变 ...
- Java 实现对文件系统的监控
在开发中经常会用到监控文件或是目录的状态,如果你还在手写轮巡扫描文件的话,那你久out了. 1. Commons io为我们提供了一套可靠.高性能的一套文件系统监控API 1.1. 需要的jar包如下 ...
随机推荐
- 六、unique_lock
一.unique_lock取代lock_guard 是个类模板,一般用lock_guard,unique_guard更灵活,效率差一点,内存占用多了一点. 二.unique_lock 的第二个参数 1 ...
- [CSP-S模拟测试]:antipalindrome(数学)
题目传送门(内部题58) 输入格式 第一行一个数$T$表示数据组数.接下来每行两个数$n$和$m$. 输出格式 $T$行,每行一个答案,对${10}^9+7$取模. 样例 样例输入: 25 66 5 ...
- python中的装饰器基本理论
装饰器 : 本质上 是一个 函数 原则 : 1,不修改原函数的源代码 2,不修改原函数的调用方式. 装饰器的知识储备 装饰器 = 高阶函数 + 函数嵌套 +闭包 我的理解是,函数名也是一个变量,将函数 ...
- 左手Mongodb右手Redis 第三章mongdb操作
mongodb查询操作 1.查询操作 db.getCollection('example_data_1').find({}) 查询所有的信息,相当于mysql中的select * from tabl ...
- vmware导出OVF文件失败
从VMware菜单栏选择导出到 .ovf. 显示导出失败 "Failed to open ..... .vmx". 尝试直接打开虚拟机,系统全部正常. 打开虚拟机所在目录,查找后缀 ...
- gradle 国内加速,修改镜像源
为什么慢 由于默认情况下执行 gradle 各种命令是去国外的 gradle 官方镜像源获取需要安装的具体软件信息,所以在不使用代理.不翻墙的情况下,从国内访问国外服务器的速度相对比较慢 如何修改镜像 ...
- Windows编写driver
1. 编译 Pspeek.cpp #include <ntddk.h> #define DANIEL_LIST_PROCESS 0x8001 PDRIVER_OBJECT daniel_D ...
- Write File in Vugen
Write a parameter to a text file in loadrunner script char *filename = "c:\\myfilename.txt&qu ...
- websocket 服务搭建
链接过程 前端 1.CREATED WEBSOCKE 2.ONOPEN 3.ONMESSAGE 服务端 1.收到request 2.给客户端发送消息,生成id //msg { type: " ...
- Asp.net core 使用log4net作为日志组件,记录日志到本地。
原文:Asp.net core 使用log4net作为日志组件,记录日志到本地. GitHub demo :https://github.com/zhanglilong23/Asp.NetCore.D ...