Форма входа
I Love Bashorg
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Форум » Программирование » Delphi » Коды ошибок в исключительных ситуациях (Обработка исключительных ситуаций)
Коды ошибок в исключительных ситуациях
BombersДата: Воскресенье, 11.04.2010, 00:08 | Сообщение # 1
Лейтенант
Группа: Администраторы
Сообщений: 62
Репутация: 0
Статус: Offline
Коды ошибок в исключительных ситуациях

Если ваше приложение уже готовится к продаже, если вы планируете его техническую поддержку, то пора задуматься о присвоении числовых кодов

Ошибкам, возникающим в нем. Сообщение типа "Exception EZeroDivide in module MyNiceProgram at addr $0781BABO" годится для разработчика, пользователя же оно повергнет в полный ступор. Если он позвонит в вашу службу техподдержки, то, скорее всего, не сможет ничего объяснить. Гораздо грамотнее дать ему уже "разжеванную" информацию и, в том числе, числовой код.

Один из путей решения этой проблемы — размещение сообщений об ошибках в ресурсах программы. Если же вы еще делаете и несколько национальных версий программы на разных языках, то этот путь — единственный.

"Классический" способ поместить текст в файл ресурсов — 3-этапный:

1. Создается исходный файл ресурсов с расширением гс, в который помещаются необходимые строки с нужными номерами.

2. Файл обрабатывается компилятором ресурсов brcc32.exe (находится в папке bin в структуре папок Delphi). На выходе образуется одноименный файл с расширением res.

3. Файл включается в программу указанием директивы $R, например

{$R mystrings.res}.

Чтобы совместно использовать константы-номера ошибок в файле ресурсов и в коде на Delphi, вынесем их в отдельный включаемый файл с расширением inc:

const

IOError = 1000;

FileOpenError = IOError + 1;

FileSaveError = IOError + 2;

InternetError = 2000;

NoConnecticnError = InternetError + 1;

ConnectionAbortedError = InternetError + 2;

Взглянув на файл, вы увидите, что ошибки в нем сгруппированы по категориям. Советуем вам поступить так же, разделив константы категорий промежутком в 1000 или даже 10 000.

Сам файл ресурсов может выглядеть так:

#include "strids.inc" STRINGTABLE

{

FileOpenError, "File Open Error"

FileSaveError, "File Save Error"

NoConnectionError, "No Connection"

ConnectionAbortedError, "Connection Aborted"

}

"Вытащить" строку из ресурсов можно несколькими способами, но самый простой из них — просто по числовому идентификатору, переданному в функцию Loadstr (модуль SysUtils). Код

ShowMessage(LoadStr(NoConnectionError) ) ;

покажет сообщение "NO connection".

Если же строка используется при возбуждении ИС, то место идентификатору—в перекрываемом конструкторе Exception.createRes, один из вариантов которого работает подобно функции Loadstr:

if FileOpent'c:\myfile.txt", fmOpenRead) = INVALID_HANDLE_VALUE then

raise EMyException.CreateRes(FileOpenError) ;

 
BombersДата: Воскресенье, 11.04.2010, 00:08 | Сообщение # 2
Лейтенант
Группа: Администраторы
Сообщений: 62
Репутация: 0
Статус: Offline
Таким образом, решена половина проблемы: возможным исключительным ситуациям присвоены номера, им в соответствие поставлен текст. Теперь о второй половине — как в обработчике ИС этот номер использовать.

Ясно, что нужно объявить свой класс ИС, включающий в себя свойство-код

ошибки.

EExceptionWithCode = class(Exception)

private

FErrCode : Integer;

public

constructor CreateResCode(ResStringRec: PResStringRec);

property ErrCode: Integer read FErrCode write FErrCode;

end;

Тогда любой обработчик сможет к нему обратиться:

if E is EExceptionWithCode then

ShowMessage('Error code: ' + IntToStr(EExceptionWithCode(E).ErrCode) +

#13*10

+ 'Error text: ' + E.Message);

Присвоить свойству ErrCode значение можно двумя способами:

1. Добавить к классу ИС еще один конструктор, содержащий код в качестве дополнительного параметра:

constructor EExceptionWithCode.CreateResCode(Ident: Integer);

begin

FErrCode := Ident;

inherited CreateRes(Ident);

end;

2. Присвоить значение свойства в промежутке между созданием объекта ИС и его возбуждением:

var E: EExceptionWithCode; begin

E := EExceptionWithCode.CreateRes(NoConnectionError);

E.ErrCode := NoConnectionError;

Raise E;

end;

Вот, казалось бы, последний штрих. Но как быть тем, кто заранее не заготовил файл ресурсов, а работает со строками, описанными в PAS-файлах? Если вы используете оператор resourcestring, то помочь вам можно.

Начнем с рассмотрения ключевого слова resourcestring. Вслед за ним описываются текстовые константы. Но, в отличие от ключевого слова const, эти константы размещаются не в сегменте данных программы, а в ресурсах, и подгружаются оттуда по мере необходимости. Каждая такая константа воспринимается и обрабатывается как обычная строка. Но за каждой из них на самом деле стоит такая структура:

PResStringRec = ^TResStringRec;

TResStringRec = packed record

Module: ^Cardinal;

Identifier: Integer;

end;

Если вы еще раз посмотрите на список конструкторов объекта Exception, вы увидите, что те из них, которые работают с ресурсами, имеют перегружаемую версию с параметром типа pResstringRec. Вы угадали правильно: они — для строк из resourcestring. А взглянув на приведенную выше структуру, вы увидите в ней поле identifier. Это то, что нам надо.

Чтобы у программиста, пользующегося resourcestring, голова не болела об уникальных идентификаторах ресурсных строк, среда Delphi берет на себя заботу об этом. Номера назначаются компилятором, начиная от 65 535 (SmallInt (-D) и ниже (если рассматривать номер как тип (SmallInt, то выше): 65 534, 65 533 и т. п. Сначала в этом списке идут несколько сотен resourcestring-констант, описанных в VCL (из модулей, чье имя заканчивается на const или consts: sysconst, DBConsts и т. п.). Затем очередь доходит до пользовательских констант (рис. 3.3).

С одной стороны, отсутствие лишних забот — это большой плюс; с другой стороны, разработчик не может задать строкам те номера, какие хочет.

Все остальное почти ничем не отличается от работы с "самодельными" ресурсами. Так выглядит перегружаемая версия конструктора нашего объекта EExceptionWithCode:

constructor EExceptionWithCode.CreateResCode(ResStringRec:

PResStringRec);

begin

FErrCode := ResStringRec^.Identifier;

inherited CreateRes(ResStringRec);

end;

А так — возбуждение самой ИС:

resourcestring sErrorl = 'Error 1';

Raise EExceptionWithCode.CreateResCode

(PResStringRec(@sErrorl));

Результат обработки показан на рис. 3.3.

Рис. 3.3. Результат обработки ИС типа EExceptionWithCode

 
Форум » Программирование » Delphi » Коды ошибок в исключительных ситуациях (Обработка исключительных ситуаций)
  • Страница 1 из 1
  • 1
Поиск:

Четверг, 28.03.2024, 19:49
Приветствую Вас Гость
Статистика
  • Admin icq status
    587643917
    Друзья сайта