Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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]
>
> > где её скачать?
>
>
> Кажись, на сайте у Анатолия Подгорецкого (С) она есть.


GOOGLE
программирование серверных приложений 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
15-1169695931
Slider007
2007-01-25 06:32
2007.02.18
С днем рождения ! 25 января


15-1169969602
Gydvin
2007-01-28 10:33
2007.02.18
DVD меню


3-1163139508
WhiteBarin
2006-11-10 09:18
2007.02.18
Текущая дата в FireBird?


15-1169618650
Бумер2
2007-01-24 09:04
2007.02.18
Бумер2


2-1170190894
Marker
2007-01-31 00:01
2007.02.18
Цветные строки в TMemo





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский