Как правильно использовать GetLastError и FormatMessage в Delphi?

У меня проблема с использованием стороннего компонента в Delphi 2006 (также Delphi 7), в котором я получаю «Неопределенную ошибку» при выполнении вызова функции для этого компонента. У вас есть пример кода, который использует GetLastError и FormatMessage в Delphi, что позволит мне получить дополнительную информацию об ошибке? TIA :)


person Drew Gibson    schedule 21.03.2009    source источник
comment
Вам нужно будет добавить больше контекста к вашему вопросу. Как на самом деле выглядит ваш код, который дает сбой? "Unspecified error" - это фактическое сообщение об ошибке системы (для кода ошибки E_FAIL), поэтому, вероятно, вы не сможете получить более подробную информацию об ошибке, в зависимости от того, что именно вы делаете. Откуда именно вы получаете сообщение об ошибке "Не указано"? И что заставляет вас думать, что сторонний компонент использует (Get|Set)LastError(), чтобы предоставить вам больше деталей, чем у вас уже есть?   -  person Remy Lebeau    schedule 11.05.2020
comment
Привет, Реми, спасибо за комментарий :). На самом деле я опубликовал это еще в 2009 году, поэтому я не могу вспомнить контекст, а тем более еще не имею кода. Ваше здоровье !   -  person Drew Gibson    schedule 13.05.2020
comment
ты прав. Виноват. Дату на вопросе не заметил. Я думаю, что недавнее изменение ответа dummzeuch поставило этот вопрос на первое место в моей ленте. Придется уделять больше внимания свиданиям.   -  person Remy Lebeau    schedule 13.05.2020


Ответы (2)


В Delphi есть встроенная вспомогательная функция: SysErrorMessage. По сути, это оболочка для FormatMessage, но в вашем случае ее гораздо проще использовать. Просто укажите код ошибки, для которой вам нужно текстовое описание.

Например, вы можете использовать это для отображения последней ошибки:

ShowMessage(SysErrorMessage(GetLastError))

Если вы хотите вызвать исключение с этим сообщением, это еще проще:

RaiseLastOSError;

Важно: убедитесь, что нет дополнительного вызова API между сбойной функцией и вашим вызовом GetLastError, в противном случае последняя ошибка будет сброшена.

person Daniel Rikowski    schedule 21.03.2009
comment
Примечание. Использование строки ресурса приведет к вызову API, поэтому вы потеряете код ошибки! - person dummzeuch; 21.10.2009

Хотя 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;

(Они являются частью модуля u_dzMiscUtils моей библиотеки dzLib, доступной здесь: https://osdn.net/projects/dzlib-tools/svn/view/dzlib/trunk/src/u_dzMiscUtils.pas?view=markup&root=dzlib-tools#l313

person dummzeuch    schedule 13.07.2009
comment
Большое спасибо за дополнительный код и ссылки :) +1 - person Drew Gibson; 15.07.2009
comment
Общая структура исключений, такая как madExcept, была бы еще лучше. - person Daniel Rikowski; 04.02.2011
comment
@DR: Да, возможно, но вопрос был не в этом. - person dummzeuch; 05.02.2011
comment
Ну, в этом случае: ни один из них не указывал контекст, в котором произошла ошибка ... - person Daniel Rikowski; 06.02.2011