以下的程序实现监控某个驱动器或目录,如果有生存*.3B文件,则对其进行改名(主要是针对DOS程序如EDIT保存.3b文件时进行修改)...
此程序在WindowsXP下调试完全正常,但是在Win98下却在 CreateFile 时提示参数错误,请高手帮忙看看,很急啊... 或者能用其他方法解决也行
代码如下:
unit UnitMain;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, Buttons,fileCtrl;type
TFrmMain = class(TForm)
Panel1: TPanel;
Label1: TLabel;
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;
Memo1: TMemo;
btnSetPwd: TBitBtn;
btnExit: TBitBtn;
GroupBox2: TGroupBox;
SpeedButton1: TSpeedButton;
ePath: TEdit;
procedure bStartClick(Sender: TObject);
procedure bStopClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure ePathDblClick(Sender: TObject);
procedure btnExitClick(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;
bBegin:boolean;
strWatchDir,strSourceExt,strTargetExt:string;
public
{ Private declarations }
public
procedure WatchRename(strFile:string);
procedure AppendStrToFile(strFile:string;strCon:string);
function FileGetSize(FileName:string): Int64;
function GenerateNewFileName(strFile,strSExt,strTExt:string):string;
{ D閏larations publiques }
end;var
FrmMain: TFrmMain;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: TFrmMain;
procedure HandleEvent;
protected
procedure Execute; override;
public
constructor Create(Form: TFrmMain);
end;constructor TWaitThread.Create(Form: TFrmMain);
begin
inherited Create(True);
FForm := Form;
FreeOnTerminate := False;
end;procedure TWaitThread.HandleEvent;
var
FileOpNotification: PFileNotifyInformation;
Offset: Longint;
strTmp,strMid:string ;
begin
with FForm do
begin
Pointer(FileOpNotification) := @FNotificationBuffer[0];
repeat
Offset := FileOpNotification^.NextEntryOffset;
strTmp := Format(SAction[FileOpNotification^.Action], [WideCharToString(@(FileOpNotification^.FileName))]);
strMid := ePath.Text + WideCharToString(@(FileOpNotification^.FileName));
if (Pos(strWatchDir, strMid)>0) then //新建文件是否属于监控目录下
begin
WatchRename(strMid);
end;// lbEvents.Items.Add(strMid);
PChar(FileOpNotification) := PChar(FileOpNotification)+Offset;
until Offset=0;
end;
// showmessage(strMid);
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;
此程序在WindowsXP下调试完全正常,但是在Win98下却在 CreateFile 时提示参数错误,请高手帮忙看看,很急啊... 或者能用其他方法解决也行
代码如下:
unit UnitMain;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, Buttons,fileCtrl;type
TFrmMain = class(TForm)
Panel1: TPanel;
Label1: TLabel;
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;
Memo1: TMemo;
btnSetPwd: TBitBtn;
btnExit: TBitBtn;
GroupBox2: TGroupBox;
SpeedButton1: TSpeedButton;
ePath: TEdit;
procedure bStartClick(Sender: TObject);
procedure bStopClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure ePathDblClick(Sender: TObject);
procedure btnExitClick(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;
bBegin:boolean;
strWatchDir,strSourceExt,strTargetExt:string;
public
{ Private declarations }
public
procedure WatchRename(strFile:string);
procedure AppendStrToFile(strFile:string;strCon:string);
function FileGetSize(FileName:string): Int64;
function GenerateNewFileName(strFile,strSExt,strTExt:string):string;
{ D閏larations publiques }
end;var
FrmMain: TFrmMain;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: TFrmMain;
procedure HandleEvent;
protected
procedure Execute; override;
public
constructor Create(Form: TFrmMain);
end;constructor TWaitThread.Create(Form: TFrmMain);
begin
inherited Create(True);
FForm := Form;
FreeOnTerminate := False;
end;procedure TWaitThread.HandleEvent;
var
FileOpNotification: PFileNotifyInformation;
Offset: Longint;
strTmp,strMid:string ;
begin
with FForm do
begin
Pointer(FileOpNotification) := @FNotificationBuffer[0];
repeat
Offset := FileOpNotification^.NextEntryOffset;
strTmp := Format(SAction[FileOpNotification^.Action], [WideCharToString(@(FileOpNotification^.FileName))]);
strMid := ePath.Text + WideCharToString(@(FileOpNotification^.FileName));
if (Pos(strWatchDir, strMid)>0) then //新建文件是否属于监控目录下
begin
WatchRename(strMid);
end;// lbEvents.Items.Add(strMid);
PChar(FileOpNotification) := PChar(FileOpNotification)+Offset;
until Offset=0;
end;
// showmessage(strMid);
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;
begin
strWatchDir := ePath.Text;
strSourceExt := '.3B';
strTargetExt := '.3BB'; 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 TFrmMain.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 TFrmMain.FormDestroy(Sender: TObject);
begin
bStop.Click;
end;procedure TFrmMain.FormCreate(Sender: TObject);
begin
FCompletionPort := 0;
FDirectoryHandle := 0;
FPOverlapped := @FOverlapped;
ZeroMemory(@FOverlapped, SizeOf(FOverlapped));
bStartClick(self);
end;procedure TFrmMain.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
bStopClick(self); 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;
bStartClick(self);
end;procedure TFrmMain.AppendStrToFile(strFile:string;strCon:string);
var
F:textfile;
begin
AssignFile(F,strFile);
try
Append(F);
except end;
try
Writeln(F,strCon);
finally
Closefile(F);
end;
end;procedure TFrmMain.WatchRename(strFile:string);
var
FN, FEXT, FDIR, FName,strNewFile,strFullNewName: string;
begin
if not FileExists(strFile) then exit; //文件不存在则返回
if FileGetSize(strFile)=0 then exit; //文件大小为0则返回
FN := strFile;
FEXT := ExtractFileExt(FN);
if UpperCase(FEXT)<>UpperCase(strSourceExt) then exit; //不是需要监控的文件扩展名则返回
FDIR := ExtractFilePath(FN);
FName := ExtractFileName(FN); strNewFile:=GenerateNewFileName(strFile,strSourceExt,strTargetExt);
try
RenameFile(FN, FDIR + strNewFile);
strFullNewName:=FDIR + strNewFile ;
memo1.Lines.add(strFullNewName);
sleep(2000);
AppendStrToFile(strFullNewName,chr(13)+FormatDateTime('yyyy年mm月dd',now())+chr(13)+FormatDateTime('hh:mm:ss',now())); //文件末尾添加当前时间
except end;
end;function TFrmMain.GenerateNewFileName(strFile,strSExt,strTExt:string):string;
var
strReverse,strNewFile,strTmp,strTmp2:string;
FN, FEXT, FDIR, FName: string;
iTmp:integer;
begin
FN := strFile;
FEXT := ExtractFileExt(FN);
FDIR := ExtractFilePath(FN);
FName := ExtractFileName(FN);
strTmp:=copy(FName,1,length(FName)-length(FEXT));
iTmp:=1;
while(FileExists(FDIR+strTmp+'~'+inttostr(iTmp)+strTExt)) do
begin
iTmp:=iTmp+1;
end;
strNewFile:=strTmp+'~'+inttostr(iTmp)+strTExt ;
result:=strNewFile;
end;function TFrmMain.FileGetSize(FileName:string): Int64;
var w32fd: TWin32FindData; h: THandle;
begin
Result := 0;
if FileName='' then Exit;
h := Windows.FindFirstFile(PChar(FileName),w32fd);
if h <> INVALID_HANDLE_VALUE then
with w32fd do Result := nFileSizeHigh * MAXDWORD + nFileSizeLow;
Windows.FindClose(h);
end;
procedure TFrmMain.btnExitClick(Sender: TObject);
begin
bStopClick(self);
application.Terminate;
end;end.
4年前就抛弃9X的开发了:)能在XP好,就OK了,XP是现在的基本配置
begin
// 提示! 改变名称可适用于其它驱动器,如第二个驱动器: '\\.\PhysicalDrive1\'
hDevice := CreateFile('\\.\PhysicalDrive0', GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
end
else // Version Windows 95 OSR2, Windows 98
hDevice := CreateFile('\\.\SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0);
wilowind(无风雪亦飘): hDevice := CreateFile('\\.\SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0);知之為知之,不知為不知,回復一點意義都沒有。
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);
把CreateFile里参数改一些试试:
FDirectoryHandle := CreateFile(PChar(ePath.Text),
General_Read or General_Write,
FILE_SHARE_READ or FILE_SHARE_WRITE,
nil,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
FDirectoryHandle := CreateFile(PChar(ePath.Text),
General_Read or General_Write,
FILE_SHARE_READ or FILE_SHARE_WRITE,
nil,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);这种改法试过来,还是不行...
这个函数还有其他函数可以替代吗,我只要能知道哪个目录及子目录有保存文件操作可以了,不一定要用这种方法...
hDevice := CreateFile('\\.\SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0);
这个方法也不行,提示系统找不到设备
这个贴子里的方法,对文件的建立操作可以监控,但是对DOS的EDIT保存的动作和COPY的动作没办法获得... 因为我用到的一个软件跟EDIT的保存类似...想不到这个问题这么麻烦.... 有知道的请不吝赐教啊...