怎么用Delphi来监控当前是否有文件正在被复制或移动??????
如果有文件正在复制或移动怎样知道当前正在复制或移动是什么文件和文件路径?????以上的是不是应该判断是否有文件贴粘好点呢?????比如:我现在复制三个文件,a.txt和b.dat和c.mp3,注意是三个文件同时复制,然后贴粘的时候程序就判断当前正在贴粘的是什么文件,文件全路径????可以做到这样子吗?
我只知道用一个线程来监控,其他就不是很懂了,请高手指教!!!!!最好能给点代码,因为这个比较急,所以我不想再花时间来研究,要是实在没有代码,给点什么提示也行,总比什么都没有好。
如果有文件正在复制或移动怎样知道当前正在复制或移动是什么文件和文件路径?????以上的是不是应该判断是否有文件贴粘好点呢?????比如:我现在复制三个文件,a.txt和b.dat和c.mp3,注意是三个文件同时复制,然后贴粘的时候程序就判断当前正在贴粘的是什么文件,文件全路径????可以做到这样子吗?
我只知道用一个线程来监控,其他就不是很懂了,请高手指教!!!!!最好能给点代码,因为这个比较急,所以我不想再花时间来研究,要是实在没有代码,给点什么提示也行,总比什么都没有好。
解决方案 »
- 关于数组元素类型的问题?
- delphi20005中面向對象的特性(比如命名空間),可以用在原生程序開發上麼?
- 在sql 2000中怎么才能把货币类型数据添加到money字段里?
- delphi里有算百分数的函数么?
- 关于强制转换,很紧急的问题!请大侠们帮帮忙!
- Delphi5 代码转 C++ Builder5-6,请各位跨越这个界限的高手看看,谢谢!
- 数据库文件的恢复是不是备份时的逆过程,只需要用copyfile把备份的数据库copy回去就可以了,拜托相告
- 帮忙解释一个错误提示
- 系统分析员、系统设计师培训讨论,参与者有分
- 修改可执行文件
- DBGirdEh如何显示access的备注类型
- c++builder版的问题,请高手解答TNMPOP3连接异常该怎么处理?
1)API hook:SHFileOperation,CopyFile等API
2)Shell Hook,可以监控Shell事件
//注册一个事件响应~~
//代码如下~~
//zswang
unit unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ShlObj, ShellAPI;const
WM_SHNOTIFY = WM_USER + 10;type
TForm1 = class(TForm)
MemoNotifyLog: TMemo;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
FNotifyHandle: THandle;
procedure WMSHNOTIFY(var Msg: TMessage); message WM_SHNOTIFY;
public
{ Public declarations }
end;var
FOrm1: Tform1;implementation{$WARNINGS OFF}
uses FileCtrl;{$R *.dfm}type
NOTIFYREGISTER = packed record
pidlPath: PItemIDList;
bWatchSubtree: BOOL;
end;
PNotifyRegister = ^NOTIFYREGISTER; function SHChangeNotifyRegister(hWnd: HWND; dwFlags: Integer;
wEventMask: Cardinal; uMsg: UINT; cItems: Integer;
lpItems: PNotifyRegister): HWND; stdcall; external Shell32 index 2; function SHChangeNotifyDeregister(hWnd: HWND): Boolean; stdcall;
external Shell32 index 4; function SHILCreateFromPath(pszPath: PChar; ppidl: PItemIDList;
rgflnOut: PDWORD): HResult; stdcall; external Shell32 index 28;
{$WARNINGS ON}procedure Tform1.FormCreate(Sender: TObject);
var
vNotifyRegister: NOTIFYREGISTER;
vAttributes: WORD;
vItemIDList: PItemIDList;
Dir: string;
const
SELDIRHELP = 1000;
begin
Dir := '我的电脑';
//if SelectDirectory(Dir, [sdAllowCreate, sdPerformCreate, sdPrompt],SELDIRHELP) then ;
Caption := '目录监视:' + Dir;
SHILCreatefromPath(PChar(Dir), @vItemIDList, @vAttributes);
vNotifyRegister.pidlPath := vItemIDList;
vNotifyRegister.bWatchSubtree := True; FNotifyHandle := SHChangeNotifyRegister(Handle, SHCNF_TYPE or SHCNF_IDLIST,
SHCNE_ALLEVENTS or SHCNE_INTERRUPT, WM_SHNOTIFY, 1, @vNotifyRegister); MemoNotifyLog.Clear;
end;procedure Tform1.FormDestroy(Sender: TObject);
begin
SHChangeNotifyDeregister(FNotifyHandle);
end;procedure Tform1.WMSHNOTIFY(var Msg: TMessage);
type
PSHNOTIFYSTRUCT = ^SHNOTIFYSTRUCT;
SHNOTIFYSTRUCT = packed record
dwItem1: PItemIDList;
dwItem2: PItemIDList;
end;
var
vBuffer: array[0..MAX_PATH] of Char;
pidlItem: PSHNOTIFYSTRUCT;
S: string;
begin
pidlItem := PSHNOTIFYSTRUCT(Msg.wParam);
SHGetPathFromIDList(pidlItem.dwItem1, vBuffer);
S := vBuffer;
SHGetPathFromIDList(pidlItem.dwItem2, vBuffer);
case Msg.lParam of //根据参数设置提示消息
SHCNE_RENAMEITEM: S := '重命名文件' + S + '为' + vBuffer;
SHCNE_CREATE: S := '建立文件 文件名:' + S;
SHCNE_DELETE: S := '删除文件 文件名:' + S;
SHCNE_MKDIR: S := '新建目录 目录名:' + S;
SHCNE_RMDIR: S := '删除目录 目录名:' + S;
SHCNE_MEDIAINSERTED: S := S + '中插入可移动存储介质';
SHCNE_MEDIAREMOVED: S := S + '中移去可移动存储介质' + S + ' ' + vBuffer;
SHCNE_DRIVEREMOVED: S := '移去驱动器' + S;
SHCNE_DRIVEADD: S := '添加驱动器' + S;
SHCNE_NETSHARE: S := '改变目录' + S + '的共享属性';
SHCNE_ATTRIBUTES: S := '改变文件目录属性 文件名' + S;
SHCNE_UPDATEDIR: S := '更新目录' + S;
SHCNE_UPDATEITEM: S := '更新文件 文件名:' + S;
SHCNE_SERVERDISCONNECT: S := '断开与服务器的连接' + S + ' ' + vBuffer;
SHCNE_UPDATEIMAGE: S := 'SHCNE_UPDATEIMAGE';
SHCNE_DRIVEADDGUI: S := 'SHCNE_DRIVEADDGUI';
SHCNE_RENAMEFOLDER: S := '重命名文件夹' + S + '为' + vBuffer;
SHCNE_FREESPACE: S := '磁盘空间大小改变';
SHCNE_ASSOCCHANGED: S := '改变文件关联';
else S := '未知操作' + IntToStr(Msg.lParam);
end;
MemoNotifyLog.Lines.Add(DateTimeTostr(Now)+' '+S);
end;end.
Left = 271
Top = 191
Width = 435
Height = 421
ActiveControl = ePath
Caption = 'ReadDirectoryChangesW demo'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
FormStyle = fsStayOnTop
OldCreateOrder = True
Position = poScreenCenter
OnCreate = FormCreate
OnDestroy = FormDestroy
PixelsPerInch = 96
TextHeight = 13
object lbEvents: TListBox
Left = 0
Top = 212
Width = 427
Height = 175
Align = alClient
ItemHeight = 13
TabOrder = 0
end
object Panel1: TPanel
Left = 0
Top = 0
Width = 427
Height = 212
Align = alTop
BevelOuter = bvNone
TabOrder = 1
object Label1: TLabel
Left = 6
Top = 43
Width = 97
Height = 13
Caption = 'Directory to monitor :'
end
object CJLabel1: TLabel
Left = 113
Top = 8
Width = 189
Height = 24
Caption = 'Directory Monitoring'
Font.Charset = DEFAULT_CHARSET
Font.Color = clNavy
Font.Height = -19
Font.Name = 'MS Sans Serif'
Font.Style = [fsBold]
ParentFont = False
end
object SpeedButton1: TSpeedButton
Left = 399
Top = 58
Width = 21
Height = 21
Glyph.Data = {
F6000000424DF600000000000000760000002800000010000000100000000100
0400000000008000000000000000000000001000000010000000000000000000
80000080000000808000800000008000800080800000C0C0C000808080000000
FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00777777777777
77777777777777777777000000000007777700333333333077770B0333333333
07770FB03333333330770BFB0333333333070FBFB000000000000BFBFBFBFB07
77770FBFBFBFBF0777770BFB0000000777777000777777770007777777777777
7007777777770777070777777777700077777777777777777777}
OnClick = ePathDblClick
end
object ePath: TEdit
Left = 5
Top = 58
Width = 394
Height = 21
Hint = 'Double-Click to display a browse dialog'
ParentShowHint = False
ShowHint = True
TabOrder = 0
OnDblClick = ePathDblClick
end
object bStart: TButton
Left = 269
Top = 184
Width = 75
Height = 25
Caption = 'Start'
TabOrder = 1
OnClick = bStartClick
end
object bStop: TButton
Left = 349
Top = 184
Width = 75
Height = 25
Caption = 'Stop'
Enabled = False
TabOrder = 2
OnClick = bStopClick
end
object ckWatchSubTree: TCheckBox
Left = 4
Top = 184
Width = 221
Height = 17
Caption = 'Also watch sub-directories events'
TabOrder = 3
end
object GroupBox1: TGroupBox
Left = 4
Top = 81
Width = 420
Height = 100
Caption = 'Events that you want to monitor'
TabOrder = 4
object ckMonitorFileName: TCheckBox
Left = 9
Top = 19
Width = 199
Height = 17
Caption = 'File Created/Deleted/Renamed'
Checked = True
State = cbChecked
TabOrder = 0
end
object ckMonitorDirName: TCheckBox
Left = 9
Top = 38
Width = 199
Height = 17
Caption = 'Directory Created/Renamed/Deleted'
TabOrder = 1
end
object ckMonitorAttributes: TCheckBox
Left = 9
Top = 56
Width = 199
Height = 17
Caption = 'File or Directory Attributes changed'
TabOrder = 2
end
object ckMonitorSize: TCheckBox
Left = 9
Top = 75
Width = 199
Height = 17
Caption = 'File size changed'
TabOrder = 3
end
object ckMonitorLastWrite: TCheckBox
Left = 215
Top = 38
Width = 201
Height = 17
Caption = 'File or Dir Last Write Date changed'
Checked = True
State = cbChecked
TabOrder = 4
end
object ckMonitorSecurity: TCheckBox
Left = 215
Top = 56
Width = 201
Height = 17
Caption = 'File or Dir Security Attributes changed'
TabOrder = 5
end
object ckMonitorCreationDate: TCheckBox
Left = 215
Top = 19
Width = 201
Height = 17
Caption = 'File or Dir Creation Date changed'
TabOrder = 6
end
object ckMonitorLastAccess: TCheckBox
Left = 215
Top = 75
Width = 201
Height = 17
Caption = 'File or Dir Last Access Date changed'
TabOrder = 7
end
end
end
end
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, Buttons;type
TForm1 = class(TForm)
lbEvents: TListBox;
Panel1: TPanel;
Label1: TLabel;
ePath: TEdit;
CJLabel1: TLabel;
bStart: TButton;
bStop: TButton;
ckWatchSubTree: TCheckBox;
GroupBox1: TGroupBox;
ckMonitorFileName: TCheckBox;
ckMonitorDirName: TCheckBox;
ckMonitorAttributes: TCheckBox;
ckMonitorSize: TCheckBox;
ckMonitorLastWrite: TCheckBox;
ckMonitorSecurity: TCheckBox;
ckMonitorCreationDate: TCheckBox;
ckMonitorLastAccess: TCheckBox;
SpeedButton1: TSpeedButton;
procedure bStartClick(Sender: TObject);
procedure bStopClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure ePathDblClick(Sender: TObject);
private
{ D閏larations priv閑s }
FDirectoryHandle: THandle;
FNotificationBuffer: array[0..4096] of Byte;
FWatchThread: TThread;
FNotifyFilter: DWORD;
FOverlapped: TOverlapped;
FPOverlapped: POverlapped;
FBytesWritten: DWORD;
FCompletionPort: THandle;
public
{ D閏larations publiques }
end;var
Form1: TForm1;type
PFileNotifyInformation = ^TFileNotifyInformation;
TFileNotifyInformation = record
NextEntryOffset: DWORD;
Action: DWORD;
FileNameLength: DWORD;
FileName: array[0..0] of WideChar;
end;const
FILE_LIST_DIRECTORY = $0001;const
SAction: array[FILE_ACTION_ADDED..FILE_ACTION_RENAMED_NEW_NAME] of String =
( 'ADDED %s',
'DELETED %s',
'MODIFIED %s',
'RENAMED %s [...]',
'[...] into %s');implementation{$R *.DFM}uses
ShlObj, ActiveX;type
TWaitThread = class(TThread)
private
FForm: TForm1;
procedure HandleEvent;
protected
procedure Execute; override;
public
constructor Create(Form: TForm1);
end;constructor TWaitThread.Create(Form: TForm1);
begin
inherited Create(True);
FForm := Form;
FreeOnTerminate := False;
end;procedure TWaitThread.HandleEvent;
var
FileOpNotification: PFileNotifyInformation;
Offset: Longint;
begin
with FForm do
begin
Pointer(FileOpNotification) := @FNotificationBuffer[0];
repeat
Offset := FileOpNotification^.NextEntryOffset;
lbEvents.Items.Add(Format(SAction[FileOpNotification^.Action], [WideCharToString(@(FileOpNotification^.FileName))]));
PChar(FileOpNotification) := PChar(FileOpNotification)+Offset;
until Offset=0;
end;
end;procedure TWaitThread.Execute;
var
numBytes: DWORD;
cbOffset: DWORD;
CompletionKey: DWORD;
begin
while not Terminated do
begin
GetQueuedCompletionStatus( FForm.FCompletionPort, numBytes, CompletionKey, FForm.FPOverlapped, INFINITE);
if CompletionKey <> 0 then
begin
Synchronize(HandleEvent);
with FForm do
begin
FBytesWritten := 0;
ZeroMemory(@FNotificationBuffer, SizeOf(FNotificationBuffer));
ReadDirectoryChanges(FDirectoryHandle, @FNotificationBuffer, SizeOf(FNotificationBuffer), ckWatchSubTree.Checked, FNotifyFilter, @FBytesWritten, @FOverlapped, nil);
end;
end
else
Terminate;
end;
end;procedure TForm1.bStartClick(Sender: TObject);
begin
FNotifyFilter := 0;
if ckMonitorFileName.Checked then
FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_FILE_NAME;
if ckMonitorDirName.Checked then
FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_DIR_NAME;
if ckMonitorAttributes.Checked then
FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_ATTRIBUTES;
if ckMonitorSize.Checked then
FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_SIZE;
if ckMonitorLastWrite.Checked then
FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_LAST_WRITE;
if ckMonitorLastAccess.Checked then
FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_LAST_ACCESS;
if ckMonitorCreationDate.Checked then
FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_CREATION;
if ckMonitorSecurity.Checked then
FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_SECURITY;
if FNotifyFilter = 0 then
begin
ShowMessage('Vous devez monitorer au moins 1 関閚ement !');
exit;
end;
lbEvents.Clear;
FDirectoryHandle := CreateFile(PChar(ePath.Text),
FILE_LIST_DIRECTORY,
FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
nil,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS or FILE_FLAG_OVERLAPPED,
0);
if FDirectoryHandle = INVALID_HANDLE_VALUE then
begin
beep;
FDirectoryHandle := 0;
ShowMessage(SysErrorMessage(GetLastError));
exit;
end;
FCompletionPort := CreateIoCompletionPort(FDirectoryHandle, 0, Longint(pointer(self)), 0);
ZeroMemory(@FNotificationBuffer, SizeOf(FNotificationBuffer));
FBytesWritten := 0;
if not ReadDirectoryChanges(FDirectoryHandle, @FNotificationBuffer, SizeOf(FNotificationBuffer), ckWatchSubTree.Checked, FNotifyFilter, @FBytesWritten, @FOverlapped, nil) then
begin
CloseHandle(FDirectoryHandle);
FDirectoryHandle := 0;
CloseHandle(FCompletionPort);
FCompletionPort := 0;
ShowMessage(SysErrorMessage(GetLastError));
exit;
end;
ePath.Enabled := False;
bStart.Enabled := False;
bStop.Enabled := True;
FWatchThread := TWaitThread.Create(self);
TWaitThread(FWatchThread).Resume;
end;procedure TForm1.bStopClick(Sender: TObject);
begin
if FCompletionPort = 0 then
exit;
PostQueuedCompletionStatus(FCompletionPort, 0, 0, nil);
FWatchThread.WaitFor;
FWatchThread.Free;
CloseHandle(FDirectoryHandle);
FDirectoryHandle := 0;
CloseHandle(FCompletionPort);
FCompletionPort := 0;
ePath.Enabled := True;
bStart.Enabled := True;
bStop.Enabled := False;
end;procedure TForm1.FormDestroy(Sender: TObject);
begin
bStop.Click;
end;procedure TForm1.FormCreate(Sender: TObject);
begin
FCompletionPort := 0;
FDirectoryHandle := 0;
FPOverlapped := @FOverlapped;
ZeroMemory(@FOverlapped, SizeOf(FOverlapped));
end;procedure TForm1.ePathDblClick(Sender: TObject);
var
SelectionPIDL: PItemIDList;
BrowseInfo: TBrowseInfo;
ShellAllocator: IMalloc;
PathBuffer: array[0..MAX_PATH] of Char;
begin
// simplest implementation of BrowseForFolder
// to get more information refer to MSDN Library or Check Brad Stower's excellent site www.delphifreestuff.com
ZeroMemory(@BrowseInfo, SizeOf(BrowseInfo));
BrowseInfo.hwndOwner := Handle;
BrowseInfo.ulFlags := BIF_RETURNONLYFSDIRS;
CoInitialize(nil);
try
SelectionPIDL := ShBrowseForFolder(BrowseInfo);
if SelectionPIDL <> nil then
try
ZeroMemory(@PathBuffer, SizeOf(PathBuffer));
if not SHGetPathFromIDList(SelectionPIDL, @PathBuffer) then
begin
beep;
exit;
end;
ePath.Text := StrPas(@PathBuffer[0]);
finally
if SHGetMalloc(ShellAllocator) = 0 then
begin
ShellAllocator.Free(SelectionPIDL);
ShellAllocator := nil;
end;
end;
finally
CoUnInitialize;
end;
end;end.
你好,我是用shellapi来做的,能不能在复制文件的时间获取源路径文件,也就是这个文件是从那里复制过来的,复制贴粘文件的时候他会执行:SHCNE_CREATE: S := '建立文件 文件名:' + S; 可是那个S只是目标文件路径,怎么取得当前这个S目标文件的原路径文件,谢谢!
网上只有ICopyHook监控文件夹,没有监控文件来的。