Форум: "Основная";
Текущий архив: 2007.02.18;
Скачать: [xml.tar.bz2];
ВнизОбработка искл. ситуаций в WinNT Service Найти похожие ветки
← →
Прогер (2006-12-22 08:30) [0]Глобальная переменная TApplication для EXE предусматривает обработчик (событие) OnException, с помощью которого я протоколирую все возникающие исключительные ситуации. Но это в приложении (EXE). А как быть с сервисом?
← →
Сергей М. © (2006-12-22 08:50) [1]А оч просто.
Тела всех назначенных тобой обработчиков событий заключай в try..except
← →
Прогер (2006-12-22 08:54) [2]Да муторно, знаете ли, батенька... :)
Можно, конечно, и так:
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 09:08) [3]
> муторно, знаете ли, батенька
А сервисы, уважаемый, вообще муторная штука)
Здесь надо понимать, что обработчики основных сервисных событий OnStart/Stop/Execute выполняются в контекстах соответствующих доп.потоков.
Одно и то же сервис-приложение может создать более чем один сервис-объект, и каждый из этих объектов создаст свой доп.поток, в котором соотв.сервис и будет "крутиться по хозяйству". Эти доп.потоки независимы друг от друга, обработка исключений в каждом из них возлагается на сам поток.
Тот код, что ты привел в [2], будет обрабатывать искл-я, возникающие лишь в основном потоке процесса сервис-приложения.
← →
oxffff © (2006-12-22 09:27) [4]
>Прогер (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% случаев твой вариант батенька ошибочный.
← →
oxffff © (2006-12-22 09:31) [5]А вообще батенька открой синенькую книжку Рихтера.
И читай до посинения.
← →
Сергей М. © (2006-12-22 09:42) [6]
> oxffff © (22.12.06 09:27) [4]
Это из другой оперы.
А текущая опера - это TServiceApplication, и реализация метода Run у него, мягко говоря, иная, хотя концептуально не отличается - организован тот же цикл ожидания/выборки/диспетчеризации сообщений.
← →
Прогер (2006-12-22 09:43) [7]
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:45) [8]
> где её скачать?
Кажись, на сайте у Анатолия Подгорецкого (С) она есть.
← →
oxffff © (2006-12-22 09:55) [9]
> Сергей М. © (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 10:02) [10]
> Прогер (22.12.06 08:54) [2]
Могу предложить "извращенный" способ глобального перехвата искл-й в сервис-процессе, хотя ты вряд ли его потянешь.
Суть метода заключается в перехвате либо вызова метода TEventLogger.LohMessage либо непосредственно WinAPI-ф-ции ReportEvent()
Впрочем, наверно есть более простой и документированный способ получения от системы уведомлений о событиях записи приложением инф-ции в сист.лог. Спроси у Игоря Шевченко (с), он, думаю, подскажет куда копать.
← →
Прогер (2006-12-22 10:40) [11]
> бработчик приведенный [2] сработает только тогда сервис
> уже "отвалится".
Смысл в том, чтобы протоколировать все исключительные ситуации, у которых нет "локального" try...except.
← →
Сергей М. © (2006-12-22 10:51) [12]
> Прогер (22.12.06 10:40) [11]
Что значит "проконтролировать" ?
Если просто вести протокол, так он и так уже ведется объектом Application, без необходимости твоего явного вмешательства. Инф-ция о необработанных исключениях исправно записывается в системный лог, там ты все это и увидишь.
← →
oxffff © (2006-12-22 11:02) [13]
> Прогер (22.12.06 10:40) [11]
>
> > бработчик приведенный [2] сработает только тогда сервис
>
> > уже "отвалится".
>
>
> Смысл в том, чтобы протоколировать все исключительные ситуации,
> у которых нет "локального" try...except.
Так если нет локального "try...except".
управление выйдет за RUN, а перед еще и вызовет StartThread.Free;
Ты только запротоколируешь "падение сервиса".
← →
Прогер (2006-12-22 11:34) [14]
> Инф-ция о необработанных исключениях исправно записывается
> в системный лог, там ты все это и увидишь.
В журнале такая вот запись. Как так?
Сбой при запуске службы "имя" из-за ошибки: "имя" не является приложением Win32.
← →
Сергей М. © (2006-12-22 11:38) [15]А это не твой сервис такое исключение выдал. До его запуска дело вообще не дошло, судя по тексту в записи.
← →
Прогер (2006-12-22 11:45) [16]
> А это не твой сервис такое исключение выдал.
Боюсь, что мой. Только вот почему?
Раньше писал сервисы на Win2000, работало. Сейчас (первый раз) для WinXP. Создал "пустой" сервис - та же ошибка в системном журнале. В чём дело, понять не могу.
← →
Сергей М. © (2006-12-22 11:51) [17]
> Боюсь, что мой
Не надо гадать.
Если сервис-приложение стартует, то ты поймаешь брейкпойнт на первой же его строчке.
← →
Сергей М. © (2006-12-22 11:56) [18]Более того, если бы ошибка была именно в твоем коде, в лог была бы записана строчка вида "Service failed on ...", а не та что ты наблюдаешь.
← →
Прогер (2006-12-22 12:05) [19]С точками останова в сервисе проблема. Не успеваю к процессу подключиться. Поэтому отладку произвожу либо догадками, либо на основе протокола (локальные try...except).
Само сообщение "...не является приложением Win32" наводит на плохую мысль об ошибке, допущенной компилятором. Хотя с ключами -install, -uninstall отрабатывает с соответствующими сообщениями. Сервисы самой ОС, от антивируса и другие (не мои) работат без проблем.
← →
Прогер (2006-12-22 12:08) [20]После попытки запуска сервиса появляется сообщение:
---------------------------
Службы
---------------------------
Не удалось запустить службу A123Service1 на Локальный компьютер.
Ошибка 193: 0xc1
---------------------------
ОК
---------------------------
А в системном журнале: "... не явл-ся прил. Win32".
← →
Сергей М. © (2006-12-22 12:18) [21]
> Не успеваю к процессу подключиться
см. стандартную справку "Debugging service applications"
> Само сообщение "...не является приложением Win32" наводит
> на плохую мысль об ошибке, допущенной компилятором
С трудом в это верится.
Т.е. ты утверждаешь, что ты сгенерировал ехе-файл сервис-приложения средствами соответствующего IDE-эксперта, при этом не внеся в текст проекта никаких изменений, инсталляция прошла якобы успешно (о чем имеются соотв.записи в реестре) и в результате имеешь вот такую картину при попытке старта сервиса ?
← →
Прогер (2006-12-22 12:21) [22]Установил сервис на другой компьютер (тоже WinXP SP2 rus) - работает!
← →
Сергей М. © (2006-12-22 12:24) [23]Ну вот)
Все, оказывается, расчудесно работает.
А ты, понимаешь ли, развел бодягу про исключения)
← →
Прогер (2006-12-22 12:25) [24]
> Т.е. ты утверждаешь, что ты сгенерировал ехе-файл сервис-
> приложения средствами соответствующего IDE-эксперта, при
> этом не внеся в текст проекта никаких изменений, инсталляция
> прошла якобы успешно (о чем имеются соотв.записи в реестре)
> и в результате имеешь вот такую картину при попытке старта
> сервиса ?
В Delphi7 Создать - ServiceAppl. Изменения: страрт вручную, отображаемое в консоли имя сервиса, OnStart (Started:= True;), OnStop (Stopped = True;). Ну мелочь в общем. Функционала никакого - просто запуск и останов.
Реестр не смотрел, после запуска с -install появляется сообщение "Service installed succ".
← →
Прогер (2006-12-22 12:27) [25]
> А ты, понимаешь ли, развел бодягу про исключения)
Окей, всё прекрасно. На чужом компьютере. А что же на моём? Куда копать-то... прям не знаю. Винду переустанавливать не охота...
← →
Сергей М. © (2006-12-22 12:27) [26]
> Прогер (22.12.06 12:25) [24]
Ну это уже не существенно, раз на другой машине все работает.
← →
Сергей М. © (2006-12-22 12:30) [27]
> Прогер (22.12.06 12:27) [25]
Попробуй программно стартовать свой сервис.
см. StartService() и пр. ф-ции для обеспечения работы оной.
Возможно код отказа, возвращенный по GetLasError при возврате ф-цией False, прояснит ситуацию.
← →
Прогер (2006-12-22 13:37) [28]
> Возможно код отказа, возвращенный по GetLasError при возврате
> ф-цией False, прояснит ситуацию
Код 193
{ %1 is not a valid Windows NT application. }
ERROR_BAD_EXE_FORMAT = 193;
← →
Сергей М. © (2006-12-22 13:44) [29]Жуть какая) ...
Все-таки загляни в реестр, проверь правильность регистр.записей для этого сервиса
← →
Прогер (2006-12-22 13:46) [30]
> Все-таки загляни в реестр, проверь правильность регистр.
> записей для этого сервиса
Ещё бы понимать, что должно быть прописано в реестре :)
В общем, на днях переустанавлю ОС. Вот хохма будет, если ошибка сохраниться! :)
← →
BiN © (2006-12-22 13:47) [31]
> Сергей М. © (22.12.06 13:44) [29]
>
> Жуть какая) ...
>
> Все-таки загляни в реестр, проверь правильность регистр.
> записей для этого сервиса
Думаю, именно в этом и дело. Т.к. борланд почему-то не следует рекомендации msdn:
lpBinaryPathName
[in] ... If the path contains a space, it must be quoted so that it is correctly interpreted.
← →
BiN © (2006-12-22 13:48) [32]
> Прогер (22.12.06 13:46) [30]
>
>
> Ещё бы понимать, что должно быть прописано в реестре :)
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\<Имя службы>\ImagePath
← →
Сергей М. © (2006-12-22 13:56) [33]
> BiN © (22.12.06 13:47) [31]
Ну это легко проверить, разместив ехе-файл сервис-приложения по идентичному пути на той машине, где сервис успешно до этого стартовал.
Другой вопрос, почему система выдает такую идиотскую ошибку ?
Впрочем, это не новость. Схожая ситуация наблюдается при попытке загрузки заведомо существующего dll-модуля по заведомо корректному пути: если ф-ция DllMain() вернула не 0, система кричит, мол, указанный файл по указанному пути не найден, что есть очевидная ерунда.
← →
BiN © (2006-12-22 14:06) [34]
> Сергей М. © (22.12.06 13:56) [33]
>
> Другой вопрос, почему система выдает такую идиотскую ошибку
> ?
>
> Впрочем, это не новость. Схожая ситуация наблюдается при
> попытке загрузки заведомо существующего dll-модуля по заведомо
> корректному пути: если ф-ция DllMain() вернула не 0, система
> кричит, мол, указанный файл по указанному пути не найден,
> что есть очевидная ерунда.
Странно. У меня вот выдала "System Error. Code: 1114.
A dynamic link library (DLL) initialization routine failed".
← →
Прогер (2006-12-22 14:08) [35]
> HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\<Имя
> службы>\ImagePath
Указан полный путь поиска EXE-файла с сервисом. Если всю строку взять в двойные кавычки - ЗАПУСКАЕТСЯ!!!
← →
Прогер (2006-12-22 14:11) [36]Большое прогерское СПАСИБО за обсуждение темы!
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2007.02.18;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.05 c