7

他のアプリケーション (Proxifier) からのセッション ログをメモに記録しようとしています。コマンドを使用してみました:

procedure TForm1.TimerTimer(Sender: TObject);
begin
  Memo1.Lines.LoadFromFile('C:\PMASSH\Proxyfier\Profiles\Log.txt');
end;

しかし、特定の時間にエラーが発生します

ここに画像の説明を入力

上記の問題を解決できますか? すべての回答に本当に感謝しています。

ありがとう

4

4 に答える 4

7

他のプログラムが、他のプロセスによる読み取りを許可しない共有モードでファイルを開きました。通常、これは他のアプリケーションがファイルに書き込んでいるときに発生します。

これについてあなたができることはたくさんありません。これは完全に正常な動作であり、予期されることです。エラーを検出し、しばらく待ってから再試行できます。

これはすでにタイマーで実行しているため、再試行が行われます。したがって、おそらくこれらの例外を抑制する必要があります。

procedure TForm1.TimerTimer(Sender: TObject); 
begin
  try
    Memo1.Lines.LoadFromFile(...);
  except
    on EFOpenError do
      ; //swallow this error
  end;
end;

検出EFOpenErrorはおそらく少し粗雑であることに注意してください。おそらく、そのエラーにつながる他の障害モードがあります。ただし、最初のパスとして、上記のコードはまともなスタートです。

于 2012-11-23T17:35:05.683 に答える
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 の回答のような適切な例外管理が引き続き必要であることに注意してください。

于 2012-11-23T20:17:11.080 に答える
2

ReadFileWinAPIで運試しをすることができます。共有読み取りオープンモードでは、最後のファイルバッファフラッシュでファイルの内容をこっそりと読み取ることができます。別のアプリケーション(プロキシー)が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;

これがお役に立てば幸いです...

于 2012-11-23T19:49:26.547 に答える
-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;
于 2014-10-15T09:11:04.987 に答える