【问题标题】:What is the correct usage of GetLastError and FormatMessage in Delphi?Delphi中GetLastError和FormatMessage的正确用法是什么?
【发布时间】:2010-10-14 17:18:00
【问题描述】:

我在 Delphi 2006(也是 Delphi 7)中使用第三方组件时遇到问题,在执行对该组件的函数调用时出现“未指定错误”。您是否有在 Delphi 中使用 GetLastError 和 FormatMessage 的示例代码,可以让我访问有关错误的更多信息? TIA :)

【问题讨论】:

  • 您将不得不为您的问题添加更多上下文。您的代码实际上看起来像什么失败了? "Unspecified error" 是实际的系统错误消息(对于 E_FAIL 错误代码),因此您可能无法获得有关失败的更多详细信息,具体取决于您正在执行的操作。您从哪里得到“未指定的错误”消息?是什么让您认为 3rd 方组件利用 (Get|Set)LastError() 为您提供比您已有的更多详细信息?
  • 嗨,雷米,感谢您的评论 :)。我实际上是在 2009 年以这种方式发布的,所以我不记得上下文,更不用说还有代码了。干杯!
  • 你是对的。我的错。我没有注意到问题上的日期。我认为 dummzeuch 最近对他的回答所做的编辑将这个问题带到了我的提要的顶部。我必须更加注意日期。

标签: delphi winapi error-handling


【解决方案1】:

Delphi 中有一个集成的辅助函数:SysErrorMessage。它本质上是FormatMessage 的包装器,但在您的情况下使用起来要简单得多。只需提供您需要文字说明的错误代码即可。

例如,您可以使用它来显示最后一个错误:

ShowMessage(SysErrorMessage(GetLastError))

如果你想用这个消息引发异常,那就更简单了:

RaiseLastOSError;

重要提示:确保失败的函数和你的GetLastError调用之间没有额外的API调用,否则最后的错误将被重置。

【讨论】:

  • 注意:使用资源字符串会导致API调用,所以会丢失错误码!
【解决方案2】:

虽然 DR 是正确的,但这种方法存在一个问题:它不允许您指定发生错误的上下文。见过错误“API 函数失败”。不知道它是哪个功能以及它发生在哪里?

这就是我编写 RaiseLastOsErrorEx 和 Win32CheckEx 函数的原因:

procedure RaiseLastOsErrorEx(const _Format: string);
begin
  RaiseLastOsErrorEx(GetLastError, _Format);
end;

procedure RaiseLastOsErrorEx(_ErrorCode: integer; _Format: string); overload;
var
  Error: EOSError;
begin
  if _ErrorCode <> ERROR_SUCCESS then
    Error := EOSError.CreateFmt(_Format, [_ErrorCode, SysErrorMessage(_ErrorCode)])
  else
    Error := EOsError.CreateFmt(_Format, [_ErrorCode, _('unknown OS error')]);
  Error.ErrorCode := _ErrorCode;
  raise Error;
end;

function GetLastOsError(out _Error: string; const _Format: string = ''): DWORD;
begin
  Result := GetLastOsError(GetLastError, _Error, _Format);
end;

function GetLastOsError(_ErrCode: integer; out _Error: string; const _Format: string = ''): DWORD;
var
  s: string;
begin
  Result := _ErrCode;
  if Result <> ERROR_SUCCESS then
    s := SysErrorMessage(Result)
  else
    s := _('unknown OS error');
  if _Format <> '' then
    try
      _Error := Format(_Format, [Result, s])
    except
      _Error := s;
    end else
    _Error := s;
end;

function Win32CheckEx(_RetVal: BOOL; out _ErrorCode: DWORD; out _Error: string;
  const _Format: string = ''): BOOL;
begin
  Result := _RetVal;
  if not Result then
    _ErrorCode := GetLastOsError(_Error, _Format);
end;

(它们是我的 dzLib 库的 u_dzMiscUtils 单元的一部分,可在此处获得: https://osdn.net/projects/dzlib-tools/svn/view/dzlib/trunk/src/u_dzMiscUtils.pas?view=markup&root=dzlib-tools#l313

【讨论】:

  • 非常感谢您提供的附加代码和链接 :) +1
  • 像 madExcept 这样的通用异常框架会更好。
  • @DR:是的,也许吧,但这不是问题所在。
  • 好吧,在那种情况下:“指定发生错误的上下文”也不是...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-05
  • 1970-01-01
  • 2020-09-14
  • 1970-01-01
  • 2011-08-22
  • 2013-03-09
相关资源
最近更新 更多