Искусство управления ошибкамиDelphi , Синтаксис , Ошибки и ИсключенияИскусство управления ошибками
Оформил: DeeCo Автор: Даутов Ильдар Часть IIПродолжая тему "Управление ошибками в Delphi", поставим следующие задачи :
Монитор ошибок Оформить программу как сервис Windows NT (Win32 service) не составляет большого труда :
ErrorMonitorService.exe /install Удаление сервиса : ErrorMonitorService.exe /uninstall Запуск сервиса выполняется из командной строки следующим образом : net start ErrorMonitor Останов сервиса : net stop ErrorMonitor Оформив эту последовательность команд как BAT-файл, можно значительно облегчить себе жизнь при отладке сервиса. Достаточно подробную информацию о сервисах Windows NT можно найти в книге : А.В.Фролов, Г.В.Фролов 'Программирование для Windows NT (часть вторая)', Москва, ДИАЛОГ-МИФИ, 1997 Для сохранения протокола (журнала) пользовательских ошибок используем следующую схему :
unit uErrorMonitorService; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, ScktComp; type TErrorMonitor = class(TService) procedure Service1Execute(Sender: TService); procedure ServiceEMCreate(Sender: TObject); private public function GetServiceController: PServiceController; override; procedure SendError; function InitLog: boolean; end; var ErrorMonitor: TErrorMonitor; implementation uses Dialogs; {$R *.DFM} const LogDir = 'C:\Log\'; // каталог, где сохраняются журналы var LogFile: TextFile; // файл текущего журнала LogName: string; // имя файла текущего журнала h: THandle; // handle канала Mailslot str: string[250]; // буфер для передачи информации MsgNumber, MsgNext, Read: DWORD; procedure ServiceController(CtrlCode: DWord); stdcall; begin ErrorMonitor.Controller(CtrlCode); end; function TErrorMonitor.GetServiceController: PServiceController; begin Result := @ServiceController; end; // Передача текста ошибки от сервиса программе просмотра procedure TErrorMonitor.SendError; var h: THandle; i: integer; begin // открытие MailSlot-канала, по которому будет передаваться протокол // используется широковещательная передача в домене h := CreateFile(PChar('\\*\mailslot\EMonMess'), GENERIC_WRITE, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0); if h <> INVALID_HANDLE_VALUE then begin // запись в канал и закрытие канала WriteFile(h, str, Length(str) + 1, DWORD(i), nil); CloseHandle(h); end; end; // инициализация файла журнала // журналы ведутся в отдельных файлах по каждой дате function TErrorMonitor.InitLog: boolean; var sr: TSearchRec; i: integer; begin Result := True; // удаление старых файлов журнала //(сохраняются только последние 7 журналов) with TStringList.Create do begin Sorted := True; i := FindFirst(LogDir + '*.log', faAnyFile, sr); while i = 0 do begin Add(sr.Name); i := FindNext(sr); end; FindClose(sr); if Count > 7 then for i := 0 to Count - 8 do DeleteFile(LogDir + Strings[i]); Free; end; // текущий файл журнала LogName := LogDir + FormatDateTime('yyyy-mm-dd', Date) + '.log'; AssignFile(LogFile, LogName); try if FileExists(LogName) then Append(LogFile) else Rewrite(LogFile); except str := 'Ошибка создания файла журнала : ' + LogName; Status := csStopped; LogMessage(str); ShowMessage(str); Result := False; end; end; // основная логика сервиса procedure TErrorMonitor.Service1Execute(Sender: TService); begin // создание MailSlot-канала с именем EMon - по этому имени к нему // будут обращаться клиенты, у которых возникли ошибки h := CreateMailSlot('\\.\mailslot\EMon', 0, MAILSLOT_WAIT_FOREVER, nil); if h = INVALID_HANDLE_VALUE then begin Status := csStopped; // запись в журнал событий NT str := 'Ошибка создания канала EMon !'; LogMessage(str); ShowMessage(str); Exit; end; // создание файла журнала if not InitLog then Exit; try while not Terminated do begin // определение наличия сообщения в канале if not GetMailSlotInfo(h, nil, DWORD(MsgNext), @MsgNumber, nil) then begin Status := csStopped; str := 'Ошибка сбора информации канала EMon !'; LogMessage(str); ShowMessage(str); Break; end; if MsgNext <> MAILSLOT_NO_MESSAGE then begin beep; // чтение сообщения из канала и добавление в текст протокола if ReadFile(h, str, 200, DWORD(Read), nil) then begin // запись в журнал Writeln(LogFile, str); // посылка сообщения для показа SendError; end else begin str := 'Ошибка чтения сообщения !'; Writeln(LogFile, str); SendError; end; Flush(LogFile); end; sleep(500); ServiceThread.ProcessRequests(False); end; finally CloseHandle(h); CloseFile(LogFile); end; end; procedure TErrorMonitor.ServiceEMCreate(Sender: TObject); begin // под таким именем наш сервис будет виден в Service Control Manager DisplayName := 'ErrorMonitor'; // необходимо при использовании ShowMessage InterActive := True; end; end. Окно просмотра ошибок unit fErrorMonitorMessage; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ScktComp; type TfmErrorMonitorMessage = class(TForm) // протокол текущих ошибок meErrorTextNow: TMemo; meJournals: TMemo; // таймер для опроса канала Timer: TTimer; paJournals: TPanel; buJournals: TButton; lbJournals: TListBox; laJournals: TLabel; procedure FormCreate(Sender: TObject); procedure TimerTimer(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure buJournalsClick(Sender: TObject); private public end; // сетевой разделяемый ресурс, где сохраняются журналы // (укажите здесь имя своего ресурса и обеспечьте права для доступа) const LogDir = '\\MyServer\C$\Log\'; var fmErrorMonitorMessage: TfmErrorMonitorMessage; h: THandle; // handle Mailslot-канала str: string[250]; // буфер обмена MsgNumber, MsgNext, Read: DWORD; implementation {$R *.DFM} procedure TfmErrorMonitorMessage.FormCreate(Sender: TObject); var sr: TSearchRec; i: integer; begin // создание Mailslot-канала с именем EMonMess // по этому каналу будем получать сообщения об ошибках от сервиса NT h := CreateMailSlot('\\.\mailslot\EMonMess', 0, MAILSLOT_WAIT_FOREVER, nil); if h = INVALID_HANDLE_VALUE then begin ShowMessage('Ошибка создания канала !'); Halt; end; // интервал опроса канала Mailslot - 3 секунды Timer.Interval := 3000; // таймер первоначально был выключен Timer.Enabled := True; // заполнение списка доступных журналов i := FindFirst(LogDir + '*.log', faAnyFile, sr); while i = 0 do begin lbJournals.Items.Add(sr.Name); i := FindNext(sr); end; lbJournals.ItemIndex := lbJournals.Items.Count - 1; FindClose(sr); end; procedure TfmErrorMonitorMessage.TimerTimer(Sender: TObject); var str: string[250]; begin Timer.Enabled := False; // определение наличия сообщения в канале if not GetMailSlotInfo(h, nil, DWORD(MsgNext), @MsgNumber, nil) then begin ShowMessage('Ошибка сбора информации !'); Close; end; if MsgNext <> MAILSLOT_NO_MESSAGE then begin beep; // чтение сообщения из канала и добавление в текст протокола if ReadFile(h, str, 200, DWORD(Read), nil) then meErrorTextNow.Lines.Add(str) else ShowMessage('Ошибка чтения сообщения !'); end; Timer.Enabled := True; end; procedure TfmErrorMonitorMessage.FormClose(Sender: TObject; var Action: TCloseAction); begin CloseHandle(h); end; procedure TfmErrorMonitorMessage.buJournalsClick(Sender: TObject); var Journal: TFileStream; s: string; begin // получение журнала ошибок за дату meJournals.Lines.Clear; meJournals.Lines.Add('Файл журнала ' + lbJournals.Items[lbJournals.ItemIndex]); Journal := TFileStream.Create(LogDir + lbJournals.Items[lbJournals.ItemIndex], fmOpenRead or fmShareDenyNone); SetLength(s, Journal.Size); Journal.Read(PChar(s)^, Journal.Size); meJournals.Lines.Add(s); Journal.Free; end; end. Артикул "Искусство управления ошибками" описывает разработку программы для мониторинга и отображения ошибок на компьютере, работающем под управлением Windows NT, с помощью механизма Mailslot и текстовых файлов журналов. Комментарии и вопросыПолучайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта. :: Главная :: Ошибки и Исключения ::
|
||||
©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007 |