Delphi GetLastError 与执行包

Joc*_*c02 0 delphi winapi getlasterror delphi-xe6

当我在没有运行时包的情况下执行此代码时,出现 32 代码错误,这是正确的。但是当我激活运行时包(例如仅使用“FireDACASADriver;YmagControlDB”)时,错误代码始终为“0”

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;
Run Code Online (Sandbox Code Playgroud)

如何使用运行时包修复 GetLastError?

Dav*_*nan 5

打电话到那里根本不合适GetLastError。您正在混合两种不同的错误处理模型。

GetLastError如果文档规定这样做,则在 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;
Run Code Online (Sandbox Code Playgroud)

如果出现错误,将引发异常,并由顶级异常处理程序报告。

运行时包不应影响此代码的执行方式。

错误的可能原因是文件不存在或被锁定。

你写了:

if Assigned(Stream) then
  Stream.Free;
Run Code Online (Sandbox Code Playgroud)

这总是毫无意义的,因为该Free方法还检查对象引用是否为nil。事实上你的代码相当于:

if Assigned(Stream) then
  if Assigned(Stream) then
    Stream.Destroy;
Run Code Online (Sandbox Code Playgroud)

因此,依靠内部测试更干净Free,只需编写:

Stream.Free;
Run Code Online (Sandbox Code Playgroud)

在评论中,您声明您实际上想测试文件是否被锁定。不要为此使用文件流。相反,请执行以下操作:

  • 调用CreateFile以打开文件。
  • 检查返回的句柄INVALID_HANDLE_VALUE以检测错误。
  • 如果出现错误,请GetLastError查找错误原因。
  • 否则用 关闭手柄CloseHandle

但是,不建议这样做。您可以使用此方法来确定文件未锁定,但当您尝试读取该文件时,它已被锁定。存在固有的竞争条件。

作为一般准则,请求原谅比请求许可更好。