![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Обработка искл. ситуаций в WinNT Service [D7, WinXP]
Прогер © (2006-12-22 08:30:00)Глобальная переменная TApplication для EXE предусматривает обработчик (событие) OnException, с помощью которого я протоколирую все возникающие исключительные ситуации. Но это в приложении (EXE). А как быть с сервисом?
Прогер (2006-12-22 11:45:00) [21]
> А это не твой сервис такое исключение выдал.
Боюсь, что мой. Только вот почему?
Раньше писал сервисы на Win2000, работало. Сейчас (первый раз) для WinXP. Создал "пустой" сервис - та же ошибка в системном журнале. В чём дело, понять не могу.
Сергей М. (2006-12-22 11:38:00) [22]А это не твой сервис такое исключение выдал. До его запуска дело вообще не дошло, судя по тексту в записи.
Прогер (2006-12-22 11:34:00) [23]
> Инф-ция о необработанных исключениях исправно записывается
> в системный лог, там ты все это и увидишь.
В журнале такая вот запись. Как так?
Сбой при запуске службы "имя" из-за ошибки: "имя" не является приложением Win32.
oxffff (2006-12-22 11:02:00) [24]
> Прогер (22.12.06 10:40) [11]
>
> > бработчик приведенный [2] сработает только тогда сервис
>
> > уже "отвалится".
>
>
> Смысл в том, чтобы протоколировать все исключительные ситуации,
> у которых нет "локального" try...except.
Так если нет локального "try...except".
управление выйдет за RUN, а перед еще и вызовет StartThread.Free;
Ты только запротоколируешь "падение сервиса".
Сергей М. (2006-12-22 10:51:00) [25]
> Прогер (22.12.06 10:40) [11]
Что значит "проконтролировать" ?
Если просто вести протокол, так он и так уже ведется объектом Application, без необходимости твоего явного вмешательства. Инф-ция о необработанных исключениях исправно записывается в системный лог, там ты все это и увидишь.
Прогер (2006-12-22 10:40:00) [26]
> бработчик приведенный [2] сработает только тогда сервис
> уже "отвалится".
Смысл в том, чтобы протоколировать все исключительные ситуации, у которых нет "локального" try...except.
Сергей М. (2006-12-22 10:02:00) [27]
> Прогер (22.12.06 08:54) [2]
Могу предложить "извращенный" способ глобальногоперехвата искл-й в сервис-процессе, хотя ты вряд ли его потянешь.
Суть метода заключается в перехвате либо вызова метода TEventLogger.LohMessage либо непосредственно WinAPI-ф-ции ReportEvent()
Впрочем, наверно есть более простой и документированный способ получения от системы уведомлений о событиях записи приложением инф-ции в сист.лог. Спроси у Игоря Шевченко (с), он, думаю, подскажет куда копать.
oxffff (2006-12-22 09:55:00) [28]
> Сергей М. © (22.12.06 09:42) [6]
>
> > oxffff © (22.12.06 09:27) [4]
>
>
> Это из другой оперы.
>
> А текущая опера - это TServiceApplication, и реализация
> метода Run у него, мягко говоря, иная, хотя концептуально
> не отличается - организован тот же цикл ожидания/выборки/диспетчеризации
> сообщений.
Благодарю за поправку.
try
while not Forms.Application.Terminated do
Forms.Application.HandleMessage;
Forms.Application.Terminate;
if StartThread.ReturnValue <> 0 then
FEventLogger.LogMessage(SysErrorMessage(StartThread.ReturnValue));
finally
StartThread.Free;
end;
Обработчик приведенный [2] сработает только тогда сервис уже "отвалится".
> Сергей М. © (22.12.06 09:45) [8]
>
> > где её скачать?
>
>
> Кажись, на сайте у Анатолия Подгорецкого (С) она есть.
программирование серверных приложений djvu
Сергей М. (2006-12-22 09:45:00) [29]
> где её скачать?
Кажись, на сайте у Анатолия Подгорецкого (С) она есть.
Прогер (2006-12-22 09:43:00) [30]
procedure TServiceApplication.Run;
function FindSwitch(const Switch: string): Boolean;
begin
Result := FindCmdLineSwitch(Switch, ['-', '/'], True);
end;
var
ServiceStartTable: TServiceTableEntryArray;
ServiceCount, i, J: Integer;
StartThread: TServiceStartThread;
begin
AddExitProc(DoneServiceApplication);
if FindSwitch('INSTALL') then
RegisterServices(True, FindSwitch('SILENT'))
else if FindSwitch('UNINSTALL') then
RegisterServices(False, FindSwitch('SILENT'))
else
begin
Forms.Application.OnException := OnExceptionHandler;
ServiceCount := 0;
for i := 0 to ComponentCount - 1 do
if Components[i] is TService then Inc(ServiceCount);
SetLength(ServiceStartTable, ServiceCount + 1);
FillChar(ServiceStartTable[0], SizeOf(TServiceTableEntry) * (ServiceCount + 1), 0);
J := 0;
for i := 0 to ComponentCount - 1 do
if Components[i] is TService then
begin
ServiceStartTable[J].lpServiceName := PChar(Components[i].Name);
ServiceStartTable[J].lpServiceProc := @ServiceMain;
Inc(J);
end;
StartThread := TServiceStartThread.Create(ServiceStartTable);
try
while not Forms.Application.Terminated do
Forms.Application.HandleMessage;
Forms.Application.Terminate;
if StartThread.ReturnValue <> 0 then
FEventLogger.LogMessage(SysErrorMessage(StartThread.ReturnValue));
finally
StartThread.Free;
end;
end;
end;
> А вообще батенька открой синенькую книжку Рихтера.
Быть может, добрые люди подскажут мне, где её скачать? Спасибо.
Сергей М. (2006-12-22 09:42:00) [31]
> oxffff © (22.12.06 09:27) [4]
Это из другой оперы.
А текущая опера - это T ServiceApplication, и реализация метода Run у него, мягко говоря, иная, хотя концептуально не отличается - организован тот же цикл ожидания/выборки/диспетчеризации сообщений.
oxffff (2006-12-22 09:31:00) [32]А вообще батенька открой синенькую книжку Рихтера.
И читай до посинения.
oxffff (2006-12-22 09:27:00) [33]
>Прогер (22.12.06 08:54) [2]
> Да муторно, знаете ли, батенька... :)
>
> Можно, конечно, и так:
А разве батенька так можно?
Ты посмотри реализацию RUN
procedure TApplication.Run;
begin
FRunning := True;
try
AddExitProc(DoneApplication);
if FMainForm <> nil then
begin
case CmdShow of
SW_SHOWMINNOACTIVE: FMainForm.FWindowState := wsMinimized;
SW_SHOWMAXIMIZED: MainForm.WindowState := wsMaximized;
end;
if FShowMainForm then
if FMainForm.FWindowState = wsMinimized then
Minimize else
FMainForm.Visible := True;
repeat
try
HandleMessage;
except
HandleException(Self);
end;
until Terminated;
end;
finally
FRunning := False;
end;
end;
До твоего супер обработчика дойдет только, если HandleException создаст
исключение.
А для 99.99999% случаев твой вариант батенька ошибочный.
Сергей М. (2006-12-22 09:08:00) [34]
> муторно, знаете ли, батенька
А сервисы, уважаемый, вообще муторная штука)
Здесь надо понимать, что обработчики основных сервисных событий OnStart/Stop/Execute выполняются в контекстах соответствующих доп.потоков.
Одно и то же сервис-приложение может создать более чем один сервис-объект, и каждый из этих объектов создаст свой доп.поток, в котором соотв.сервис и будет "крутиться по хозяйству". Эти доп.потоки независимы друг от друга, обработка исключений в каждом из них возлагается на сам поток.
Тот код, что ты привел в [2], будет обрабатывать искл-я, возникающие лишь в основномпотоке процесса сервис-приложения.
Прогер (2006-12-22 08:54:00) [35]Да муторно, знаете ли, батенька... :)
Можно, конечно, и так:
program proDgstSenderService;
uses
SvcMgr,
uSender in 'uSender.pas' {srvcSender: TService},
uProc in '..\..\_Gnrl\uProc.pas',
uFuncDgstSender in '..\uFuncDgstSender.pas',
uConst in '..\uConst.pas',
uRAR in '..\..\_Gnrl\uRAR.pas';
{$R *.RES}
begin
try
Application.Initialize;
Application.CreateForm(TsrvcSender, srvcSender);
Application.Run;
except
... // протоколирование в файл
end
end.
Однако, может кто подскажешь более эстетичное решение?
Сергей М. (2006-12-22 08:50:00) [36]А оч просто.
Тела всех назначенных тобой обработчиков событий заключай в try..except