在Delphi中,GetLastError和FormatMessage的正确用法是什么?

30

我在Delphi 2006(以及Delphi 7)中使用第三方组件时遇到了问题,在执行对该组件的函数调用时出现“未指定的错误”。您是否有关于如何在Delphi中使用GetLastError和FormatMessage的示例代码,以便我可以获取有关错误的更多信息?谢谢!


你需要在问题中添加更多的上下文。你的代码实际上是什么样子的,为什么会出现“未指定错误”?“未指定错误”是一个实际的系统错误消息(对于E_FAIL错误代码),所以根据你正在做的事情,你可能无法获得更多关于失败的细节。你从哪里获得了“未指定错误”的消息?你认为第三方组件利用(Get|Set)LastError()给你提供比你已经拥有的更多的细节吗? - Remy Lebeau
嗨,Remy,谢谢你的评论:)。实际上,我是在2009年发布的,所以我不记得上下文了,更别提还有代码了。干杯! - Drew Gibson
你说得对。是我的错。我没有注意到问题的日期。我认为dummzeuch最近编辑他的答案,把这个问题带到了我的动态中。我以后会更加注意日期的。 - Remy Lebeau
2个回答

71
Delphi 中有一个集成的辅助函数:SysErrorMessage。它本质上是对 FormatMessage 的包装,但在您的情况下使用起来要简单得多。只需提供您需要文本描述的错误代码即可。
例如,您可以使用此功能显示最后的错误:
ShowMessage(SysErrorMessage(GetLastError))

如果您想使用此消息引发异常,那么更简单:

RaiseLastOSError;

重要提示:确保在失败函数和您调用GetLastError之间没有其他的API调用,否则最后一个错误将被重置。


4
注意:使用资源字符串将导致 API 调用,因此您将失去错误代码!(意思是如果使用资源字符串,就无法获得错误代码) - dummzeuch

13

尽管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 - Drew Gibson
一个像madExcept这样通用的异常框架会更好。 - Daniel Rikowski
1
@DR:是的,也许是这样,但那不是问题所在。 - dummzeuch
3
那么,根据这种情况:“指定错误发生的上下文”的意思也不是... - Daniel Rikowski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接