我正在尝试将会话日志从其他应用程序(Proxifier)记录到备忘录中。 我尝试过使用命令:
procedure TForm1.TimerTimer(Sender: TObject);
begin
Memo1.Lines.LoadFromFile('C:\PMASSH\Proxyfier\Profiles\Log.txt');
end;
但在某些时候我收到错误
你能解决我上面的问题吗?我真的很感激所有答案。
由于
答案 0 :(得分:7)
另一个程序使用共享模式打开文件,该模式不允许其他进程读取它。通常,当其他应用程序写入文件时会发生这种情况。
你可以做很多事情。这是完全正常的行为,是可以预期的。您可以尝试检测错误,等待一段时间,然后重新尝试。
由于您已经在计时器上运行此功能,因此重试将会发生。所以也许你只需要压制这些例外:
procedure TForm1.TimerTimer(Sender: TObject);
begin
try
Memo1.Lines.LoadFromFile(...);
except
on EFOpenError do
; //swallow this error
end;
end;
请注意,检测EFOpenError
可能有点粗糙。也许还有其他失败模式导致该错误。但是,作为第一遍,上面的代码是一个不错的开始。
答案 1 :(得分:5)
大卫的回答是正确的。我只是想澄清为什么会这样。
答案在于代码:
procedure TStrings.LoadFromFile(const FileName: string);
var
Stream: TStream;
begin
Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
LoadFromStream(Stream);
finally
Stream.Free;
end;
end;
如您所见,访问该文件以进行共享,但不允许写入。 你可以通过自己创建文件流来解决这个问题:
Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone);
然后使用Lines.LoadFromStream()
方法将内容加载到备忘录
请注意,如果其他应用程序以独占模式打开文件(即没有共享),则问题可能存在,因此仍需要像David的答案那样正确的异常管理。
答案 2 :(得分:2)
您可以尝试使用ReadFile WinAPI。在共享读取打开模式下,您将能够在最后一个文件缓冲区刷新时潜行并读取文件的内容。如果另一个应用程序(Proxifier)使用FILE_SHARE_READ共享模式使用CreateFile WinAPI打开文件,那么只要您使用ReadFile API,就可以打开它进行读取。如果它仍然被打开以进行共享,那么Standart LoadFromFile方法将不起作用,并且您将得到相同的“锁定”错误。
但是这里有捕获..你将不得不处理缓冲区,大小和句柄......你将不得不帮助一个句柄来读取文件,用该句柄获取文件大小,用它设置一个数组大小,读取到该数组并分配,添加(无论)该数组到备忘录.. WinAPI的纯粹用法。一些简单任务的工作......
以下是如何使用WinAPI处理文件的基本示例:
其他应用程序的文件打开过程的关键假设:
var
Form1: TForm1;
logfile: Textfile;
h: THandle;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
// AssignFile(logfile, 'c:\deneme.txt');
// Rewrite(logfile);
h := CreateFile('C:\deneme.txt', GENERIC_WRITE, FILE_SHARE_READ, nil,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
Timer1.enabled := true;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Timer1.enabled := false;
// CloseFile(logfile);
CloseHandle(h);
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
str: AnsiString;
p: pointer;
buf: array of ansichar;
written: cardinal;
begin
// Writeln(logfile, 'denemeStr');
str := 'denemeStr' + #13#10;
p := pansichar(str);
SetLength(buf, length(str));
move(p^, buf[0], length(str));
WriteFile(h, buf[0], length(buf), written, nil);
FlushFileBuffers(h);
end;
如果它被分享用于阅读,那么你可以从中读取它:
procedure TForm1.Button1Click(Sender: TObject);
var
h: THandle;
buf: array of ansichar;
size, read: cardinal;
begin
Memo1.Lines.Clear;
// Memo1.Lines.LoadFromFile('c:\deneme.txt');
h := CreateFile('C:\deneme.txt', GENERIC_READ, FILE_SHARE_READ, nil,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
size := GetFileSize(h, nil);
SetLength(buf, size);
ReadFile(h, buf[0], size, read, nil);
CloseHandle(h);
Memo1.Lines.Add(pansichar(buf));
end;
希望这会有所帮助...
答案 3 :(得分:-1)
procedure TForm1.TimerTimer(Sender: TObject);
begin
Memo1.Lines.LoadFromFile('C:\PMASSH\Proxyfier\Profiles\Log.txt');//// read file path error if file notfound
// if trying to record
Memo1.Lines.SaveToFile(Path...);
end;