Обеспечение стабильной работы внешних компонент на DelphiПри работе с внешними компонентами рекомендуется тщательно отрабатывать исключительные ситуации - иначе 1С:Предприятие будет "обрушиваться" - порой, вместе с введенными пользователем данными - по мере наступления каких-либо ошибок. | | Автор статьи: Последняя редакция №1 от 16.02.06 URL: http://kb.mista.ru/article.php?id=100 | |
Ключевые слова: внешняя, компонента, исключение, ShowErrorLog, Exception, RaiseLastOSError, Delphi, Рихтер
Обработчик исключения try-except может показать ошибку пользователю и/или записать ее в текстовый файл, который позволит программисту очень легко и быстро (и даже удаленно, не выезжая "на место происшествия") понять, а в чем же была проблема у пользователя.
Кроме того, обработчик исключения позволяет возобновить работу сбоящей программы с определенной точки, чтобы факт глючности компоненты не слишком бросался в глаза (пользователи не любят, когда им что-то или кто-то бросается в глаза). Но злоупотреблять этим, маскируя от пользователя очевидные проблемы, конечно же, нельзя (подробную информацию о проблеме можно записать в текстовый лог).
Я обрабатываю исключительные ситуации так:
try
//...
//Фрагмент кода, где возможна ошибка
//...
except
on E:Exception do begin
ShowErrorLog('Ошибка чтения из COM-порта: '+E.Message);
end;
end;
Метод ShowErrorLog выдает ошибку "красненьким" в окне сообщений 1С.
procedure AddInObject.ShowErrorLog(fMessage:WideString);
var
ErrInfo: PExcepInfo;
begin
If Trim(fMessage) = '' then Exit;
New(ErrInfo);
ErrInfo^.bstrSource := c_AddinName;
ErrInfo^.bstrDescription := fMessage;
ErrInfo^.wCode:=1006;
ErrInfo^.sCode:=E_FAIL; //генерация исключения в 1С
iError.AddError(nil, ErrInfo);
end;
Поле sCode следует установить в значение E_FAIL, если ошибка должна остановить (прервать по ошибке) выполнение кода на языке 1С, либо другое значение в противном случае (эта особенность явно указана в статье на диске ИТС и не слишком явно, если вообще указана - в "Технологии создания внешних компонент").
Многие библиотечные функции Delphi генерируют исключения при ошибках, и эти исключения, конечно же, необходимо отрабатывать. Однако, при работе с более старым инструментарием - функциями Windows API - функции не возвращают исключений при ошибках, а возвращают программисту числовые значения - коды возврата. Превратить их в "нормальные" исключения можно при помощи функции RaiseLastOSError, например:
if not GetCommState(hCom,dcb) //uses Windows
then RaiseLastOSError;
Функция RaiseLastOSError анализирует код ошибки, сопоставляет ему текстовое сообщение и возвращает его же в виде исключения.
Почему исключения в данном случае удобнее? Не надо усложнять ("засорять" обработкой ошибок) основной алгоритм вашей программы. Фактически, код, "честно" контролирующий все возможные ошибки, сокращается и делается более "прозрачным" и понятным.
Вы можете легко выйти по ошибке сразу из многих циклов или вложенных процедур. Делать это алгоритмически (что равнозначно запутыванию своего кода и превращению его в "блюдо спагетти") - прямо скажем, не стоит.
Полезные сведения об обработке исключительных ситуаций (на примере С++) пишет известный автор Дж.Рихтер в своей книге - супербестселлере "Windows для профессионалов", которая настоятельно рекомендуется к прочтению.
В среде разработки .NET программисты избавлены от необходимости использовать что-то наподобие RaiseLastOSError - все системные функции генерируют исключение при ошибках.
Максимально частое применение Exception.Create("Текстовое сообщение"), или же вызов исключений конкретного типа при любых ошибках или недочетах входных данных позволит сделать программу безошибочной, легко отлаживаемой и "самотестируемой". Можно даже утверждать, что чем больше операторов вызова исключений - тем лучше. Вы заметите, как легко искать и отлаживать проблемы, если "сторожа"-RaiseException, которые о них вам сообщают, расставлены во всех ключевых точках вашей внешней компоненты. |