2016-04-08 15 views
0

実行時パッケージなしでこのコードを実行すると、32個のコードエラーが発生します。 しかし、私は(だけでexempleのために、「FireDACASADriver; YmagControlDB」)実行時パッケージをactivite時にエラーコードが常に「0」私は実行時パッケージとのGetLastErrorを修正することができますどのようにDelphi GetLastError実行パッケージ

procedure TForm1.Button1Click(Sender: TObject); 
Var 
    Stream: TStream; 
    iError : integer; 
begin 
    Stream := nil; 
    iError := -1; 
    try 
     try 
     Stream := TFileStream.Create('d:\toto.docx', fmOpenRead); 
     except 
     begin 
      iError := GetLastError; 
     end; 
     end; 
    finally 
     if Assigned(Stream) then 
     Stream.Free; 
    end; 
    showmessage('Erreur : ' + inttostr(iError)); 
end; 

答えて

4

GetLastErrorに電話するのは適切ではありません。 2つの異なるエラー処理モデルを混在させています。

API呼び出しが失敗した直後に、を呼び出してください。あなたがそれを呼び出すと、他の何かの関数がSetLastErrorを呼び出して値をリセットすることができます。

したがって、Win32関数を使用していないのでGetLastErrorに電話するのは間違っており、GetLastErrorへの呼び出しを削除する必要があります。あなたのコードは:

procedure TForm1.Button1Click(Sender: TObject); 
var 
    Stream: TStream; 
begin 
    Stream := TFileStream.Create('d:\toto.docx', fmOpenRead); 
    try 
    // ....  
    finally 
    Stream.Free; 
    end; 
end; 

エラーがある場合、例外が発生し、トップレベル例外ハンドラによって報告されます。

ランタイムパッケージは、このコードの実行方法には関係ありません。

エラーの原因としては、ファイルが存在しないか、ロックされている可能性があります。

あなたは書きました:

Freeメソッドは、オブジェクト参照が nilであるかどうかをチェックするので、常に無意味です
if Assigned(Stream) then 
    Stream.Free; 

。実際にあなたのコードは同等です:

if Assigned(Stream) then 
    if Assigned(Stream) then 
    Stream.Destroy; 

だから、Free内のテストに依存しており、単に書くことクリーナーです:コメントで

Stream.Free; 

を、あなたが実際にテストしたいと述べていますファイルがロックされているかどうか。そのためにファイルストリームを使用しないでください。代わりに次の操作を行います。

  • CreateFileを呼び出してファイルを開きます。
  • 返されたハンドルをINVALID_HANDLE_VALUEと照合してエラーを検出します。
  • エラーの場合は、エラーの原因を確認するためにGetLastErrorを使用してください。
  • それ以外の場合は、ハンドルをCloseHandleで閉じます。

ただし、これはお勧めできません。この方法を使用して、ファイルがロックされていないことを判別できますが、読み取りを試みるまでにロックされている可能性があります。固有の競争条件があります。

一般的なガイドラインとして、許可よりも許してもらう方がいいです。

+0

私はこのコードを書いて、ロックされたドキュメントを検出します。ランタイムパックのないgetLastErrorにはコード32があります。ファイルがロックされていることを検出する最良の方法は何ですか? – Joc02

+0

最新の編集を見る –

0

例外を発生させる行為は、呼び出しスレッドのエラーコードをリセットする可能性があります。例外ハンドラ内でGetLastError()を呼び出すのは適切ではありません。言われていること

TFileStreamファイルを開くに失敗した場合、例外が(ただし、実際のエラーコード)システム提供のエラーメッセージが含まれていることを上げて、例えば:

procedure TForm1.Button1Click(Sender: TObject); 
var 
    Stream: TStream; 
begin 
    try 
    Stream := TFileStream.Create('d:\toto.docx', fmOpenRead); 
    try 
     // use Stream as needed 
    finally 
     Stream.Free; 
    end; 
    except 
    on E: Exception do 
     ShowMessage('Erreur : ' + E.Message); 
    end; 
end; 

あなたはアクセスする必要がある場合エラーコードに、あなたはTFileStreamを使用することはできません、あなたが代わりに直接CreateFile()を使用する必要があります。また

procedure TForm1.Button1Click(Sender: TObject); 
var 
    hFile: THandle; 
    iError: DWORD; 
begin 
    hFile := CreateFile('d:\toto.docx', GENERIC_READ, 0, nil, OPEN_EXISTING, 0, 0); 
    if hFile <> INVALID_HANDLE_VALUE then 
    begin 
    try 
     // use hFile as needed... 
     // 
     // if you need to access the file as a TStream, you can 
     // instantiate a THandleStream passing hFile to its constructor... 
     // 
    finally 
     CloseHandle(hFile); 
    end; 
    end else 
    begin 
    iError := GetLastError; 
    ShowMessage('Erreur : ' + IntToStr(iError)); 
    if iError = ERROR_SHARING_VIOLATION then 
    begin 
     // do something... 
    end; 
    end; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    hFile: THandle; 
begin 
    hFile := CreateFile('d:\toto.docx', GENERIC_READ, 0, nil, OPEN_EXISTING, 0, 0); 
    try 
    Win32Check(hFile <> INVALID_HANDLE_VALUE); 
    try 
     // use hFile as needed... 
    finally 
     CloseHandle(hFile); 
    end; 
    except 
    on E: EOSError do 
    begin 
     ShowMessage('Erreur : ' + IntToStr(E.ErrorCode)); 
     if E.ErrorCode = ERROR_SHARING_VIOLATION then 
     begin 
     // do something... 
     end; 
    end; 
    end; 
end; 
関連する問題