【问题标题】:Why does GetLastError have an error before my program begins?为什么 GetLastError 在我的程序开始之前出现错误?
【发布时间】:2017-04-06 02:36:49
【问题描述】:

在调用ExtractShortPathName 之类的Windows API 函数包装器后使用GetLastError 时,我注意到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)

【问题讨论】:

  • 除非发生故障,否则不要调用 GetLastError。毫无意义。
  • 我得到了完全相同的结果。有趣的是,当我从uses 子句中删除SysUtils(以及所有需要它的)时,我得到错误代码50The request is not supported.)。但是@Jonathan 是对的,除非实际发生错误,否则没有理由致电GetLastError。想象一下 10 分钟前在完全不同的窗口中发生的错误。然后,无论出于何种原因,您调用GetLastError,从而返回与 10 分钟前相同的代码。
  • API 文档表明 GetLastError 仅在 a) API 调用失败时使用,并且 b) 失败的函数表明您可以使用 GetLastError 获取有关原因的更多信息。随机调用它或在记录将其设置为失败的函数中调用它而没有失败是没有意义的。除非您知道发生了错误,否则您不能调用 GetLastError,并且只有在您调用的特定函数表明它失败后才调用它。
  • 那么我是误会了什么还是做错了什么?的答案是两者都。 :-)
  • @KendallLister ExtractShortPathName 不是 Windows API 调用,它是 Delphi SysUtils 内置的,而后者又调用 GetShortPathName,这是一个 API 调用:)

标签: delphi winapi error-handling delphi-xe8


【解决方案1】:

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

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

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

您应该立即调用 GetLastError 函数 函数的返回值表明这样的调用将返回有用的 数据。

【讨论】:

    【解决方案2】:

    GetLastError 的文档表明只有在

    • API 调用失败,并且
    • 失败的函数表明您可以使用 GetLastError 获取有关原因的更多信息。 来自该文档(强调我的

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

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

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

    【讨论】:

      猜你喜欢
      • 2015-10-13
      • 1970-01-01
      • 2019-11-25
      • 2011-01-27
      • 2014-09-17
      • 2021-08-11
      • 2014-11-30
      • 2014-12-11
      • 1970-01-01
      相关资源
      最近更新 更多