为什么GetLastError在程序开始之前出错?

时间:2017-04-06 02:36:50

标签: delphi winapi error-handling delphi-xe8

在调用类似GetLastError的Windows API函数包装器后使用ExtractShortPathName时,我注意到GetLastError返回非零错误代码,无论对ExtractShortPathName的调用是否成功或失败。事实上,似乎有一个"最后一个错误"在我的程序执行之前,例如

program TestGetLastError;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils;

var
  ErrorCode: Integer;

begin
  try
    ErrorCode := GetLastError;
    if ErrorCode <> 0 then
      RaiseLastOSError;
  except
    on E: Exception do
      WriteLn(E.ClassName, ': ', E.Message);
  end;
end.

结果:

EOSError: System Error.  Code: 122.
The data area passed to a system call is too small

我误解了某些事情或做错了吗?

如果Delphi运行时正在执行导致GetLastError设置的事情,那么在程序开始执行之前清除该错误的正确方法是什么?我应该像Delphi API文档中的这个例子一样使用SetLastError(ERROR_SUCCESS);

procedure TForm2.btRaiseLastClick(Sender: TObject);
begin
  { Set the last OS error to a bogus value. }
  System.SetLastError(ERROR_ACCESS_DENIED);

  try
    RaiseLastOSError();
  except
    on Ex : EOSError do
      MessageDlg('Caught an OS error with code: ' + IntToStr(Ex.ErrorCode), mtError, [mbOK], 0);
  end;

  { Let the Delphi Exception dialog appear. }
  RaiseLastOSError(ERROR_NOT_ENOUGH_MEMORY);

  { Finally set the last error to none. }
  System.SetLastError(ERROR_SUCCESS);

  if GetLastError() <> ERROR_SUCCESS then
    MessageDlg('Whoops, something went wrong in the mean time!', mtError, [mbOK], 0);

  { No exception should be thrown here because last OS error is "ERROR_SUCCESS". }
  CheckOSError(GetLastError());
end;

http://docwiki.embarcadero.com/CodeExamples/Tokyo/en/LastOSError_(Delphi)

2 个答案:

答案 0 :(得分:13)

GetLastError()返回的值仅在失败的Windows API调用之后立即生效,并且该函数的文档通过调用GetLastError()指定扩展错误信息可用。

在该上下文之外调用它将返回先前调用的内容,该调用可能来自您的代码,Delphi运行时,您调用的DLL,甚至是Windows API中的某些内容......

正如GetLastError()所述的Windows API文档:

  

你应该在a时立即调用GetLastError函数   函数的返回值表示这样的调用将返回有用   数据

答案 1 :(得分:4)

GetLastError的文档表明仅在

时使用
  • API调用失败,
  • 失败的函数表示您可以使用GetLastError获取有关原因的更多信息。 从该文件(强调我的
  

返回值是调用线程的最后错误代码。

     

设置最后错误代码的每个函数的文档的返回值部分说明了函数设置最后错误代码的条件。设置线程的最后错误的大多数函数代码在失败时设置它。但是,某些函数在成功时也会设置最后一个错误代码。 如果没有记录该函数来设置最后错误代码,则此函数返回的值只是已设置的最新最后错误代码;某些函数在成功时将最后一个错误代码设置为0,而其他函数则不会。

这表明在没有首先记录的函数中将其设置为失败的情况下调用它是没有意义的。除非您知道发生了错误,否则不能调用GetLastError,并且只有在您调用的特定函数指示它失败后才调用它。