Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2005.01.02;
Скачать: [xml.tar.bz2];

Вниз

Как правильно запускать сервис во время проэктирования?   Найти похожие ветки 

 
TankMan ©   (2004-10-30 21:24) [0]

Пишу программку, которая работает как сервис, но вот проблема в том что когда я в процессе программирования хочу проверить работоспособность например некоторой функции, с помощью F9 пытаюсь ее запустить, но вот она тут же закрывается, приходится с помощью батника(C:\Delphi\HarDS\HarDS.exe /install /silent) запускать отдельно :(... но какая тогда к черту отладка :(...
Я впринципе сейчас как-то хило да бедно выкручиваюсь тем, что переименовываю HardS и запускаю его как сервис, и тогда когда из дельфи я запускаю проект, он запускается и висит в рабочем состоянии но почему-то не дольше минуты или пол-минуты :(...

Вобщем что-то я предысторией увлекся :)
Скажите Как нужно правильно работать с Дельфи при разработке сервисов?


 
Ученик   (2004-10-30 22:15) [1]

Help-service applications-Debugging

но проще, наверно, написать как обычное приложение, а потом сделать его сервисом :-)


 
TankMan ©   (2004-11-02 06:59) [2]

Мдааа...
You must launch the service quickly (within 15-30 seconds of application startup) because the application will terminate if no service is launched.
Но вот проблема в том что у меня прожка успевает запуститься и вылететь за секунду или две :(

Ты говоришь писать как обычное приложение а потом сделать его сервисом, но как? Я не знаю :(...
Вообще проблема остается открытой, т.к. у меня прожка уже далеко не в начале разработки :(...
Неужели нет нормального способа?


 
TankMan ©   (2004-11-05 06:53) [3]

Я вот тут дальше не разобрался в этом хелпе :(

1 First create a key called Image File Execution Options in the following registry location:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
Ну тут то ясно...
2 Create a subkey with the same name as your service (for example, MYSERV.EXE). To this subkey, add a value of type REG_SZ, named Debugger. Use the full path to the debugger as the string value.

А вот какой именно путь то указывать?(the full path to the debugger) просто до delphi или еще куда?

3 In the Services control panel applet, select your service, click Startup and check Allow Service to Interact with Desktop.
"..and check Allow Service to Interact with Desktop." как это перевести?

Вобщем все не получается ни как :(


 
Ученик   (2004-11-06 00:28) [4]

Компилируешь программу-сервис,
запускаешь ее с параметром /Install для установки сервиса,
из сервисов его стартуешь, в Delphi к нему подключаешься через Attach to Process,
проверено - работает


 
Erik1 ©   (2004-11-08 10:25) [5]

Полезней для здоровя создать еще один проект включить туда свои модули, добавить форму, на нее кнопочку со стартом потока. Далее думаю обяснять ненужно. Есть подозрение, что ты невыделил работу сервиса в отдельный поток, ну чтоз переделать никогда непоздно!
 Для меня это главный агрумент организовать сервис в дополнительном потоке.


 
GrayFace ©   (2004-11-08 14:28) [6]

TankMan ©   (05.11.04 6:53) [3]
"..and check Allow Service to Interact with Desktop."

и выбрать Разрешить сервису взаимодействовать с рабочим столом.


 
Burmistroff   (2004-11-08 23:02) [7]

Можно заинсталить сервис, потом (через консоль сервисов services.msc или net start) запускать его, затем в течении 20-30 секунд идешь в Delphi (сервис перед запуском должен был быть скомпилирован) и выбираешь Debugging | Attach to process. Выбираешь затем свой сервис и жмешь F9 (если не нажмешь, то через 20-30 секунд Windows закроет сервис, т.к. подумает что он не запустился).


 
Burmistroff   (2004-11-08 23:09) [8]

Ах да, чтобы не закрывался до подключения отладчика можно банальный Messagebox вставить.

Заодно проверь чтобы было:

procedure ServiceController(CtrlCode: DWord); stdcall;
begin
 Servicename.Controller(CtrlCode);
end;

function TServicename.GetServiceController: TServiceController;
begin
 Result := ServiceController;
end;

procedure TServicename.ServiceStart(Sender: TService; var Started: Boolean);
begin
 Started:=true;
end;

procedure TServicename.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
 Stopped:=true;
end;


 
Alex Konshin ©   (2004-11-08 23:33) [9]

Лично я писал сервисный модуль так, чтобы он мог работать и как сервис, и из командной строки (примерно как Apache webserver). Соответственно, больших проблем с отладкой у меня не было.
Сам проект при этом практически не изменился. IMHO я использовал  модифицированный чей-то класс для сервисов (тогда еще не было стандартного проекта для сервиса в Delphi).
Если не забуду, то когда дойду до дома расскажу подробнее.


 
Alex Konshin ©   (2004-11-09 07:14) [10]

Ну вот, смотрите http://home.earthlink.net/~akonshin/files/AcntService.pas

Оказывается, я там хитрю еще больше, чем думал:

// Реализация сервиса отличается от общепринятой:
//  обычно из ServiceMain стартуют нить, которая и будет выполнять полезную
//  работу, но нить ServiceMain стартует service manager и я подозреваю,
//  что именно поэтому по любому exception все рушится.
//  Поэтому я создаю нить еще перед запуском сервиса из главной(первой) нити процесса,
//  и она дожидается команды от ServiceMain нити.

На мой взгляд, это довольно удачное решение: мы таким образом гарантируем, что нить создана правильно с точки зрения механизма обработки исключений Delphi и заодно само приложение получается простым как валенок. Дело в том, что для корректной работы исключений нить должна быть создана через BeginThread.
Да, как этим пользоваться:
Нужно написать класс-наследник от TAcntService, в котором перекрыть DoEvent и Execute (если нужно). Там уже организован цикл ожидания событий, что типично для сервисов (ждем запроса - обрабатываем, и так по кругу). Смотрите пример dpr:
http://home.earthlink.net/~akonshin/files/FlarpService.pas
Приложение должно выдавать маленькое описание параметров при вызове его с аргументом "-?"

Эх, и давно это было...


 
TankMan ©   (2004-11-10 09:25) [11]

Ну ничего себе... 8)..я так почитал и понял что я вообще ничего о сервисах и как их запускать, не знал :(... я не читал ничего по этому поводу... так просто ткнулся - заработало :)

>>Erik1
Не мог бы выслать примерчик такого проэкта? Мне нужно чтоб была одна форма с таймером а дальше я сам разберусь :)...
У меня в 3х моих книгах ничего хорошего не было написано про Сервисы...если мне не изменяет память так там вообще ничего про сервисы небыло сказано :)


 
TankMan ©   (2004-11-10 09:32) [12]

>>Ученик
Спасибо Попробую на работе...

>>Alex Konshin
Спасибо за помощь, но вот 2й файл почему-то не качается :(

>>Burmistroff
procedure TServicename.ServiceStart(Sender: TService; var Started: Boolean);
begin
Started:=true;
end;

procedure TServicename.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
Stopped:=true;
end;
А что за переменные Stopped Started ?
У меня вот что -
procedure THarDStarter.ServiceExecute(Sender: TService);
begin
//  ShowMessage("Start executing.");
 SetPriorityClass(GetCurrentprocess,IDLE_PRIORITY_CLASS);
 StartTimer.Enabled:=true;
 while not Terminated do
 begin
   ServiceThread.ProcessRequests(False);
 end;

И вот такой вот Stop

function ServiceStop(aMachine, aServiceName: String): Boolean;
var
 h_manager, h_svc: SC_Handle;
 ServiceStatus: TServiceStatus;
 dwCheckPoint: DWORD;
begin
 h_manager := OpenSCManager(PChar(aMachine), nil, SC_MANAGER_CONNECT);
 if h_manager > 0 then
 begin
   h_svc := OpenService(h_manager, PChar(aServiceName),
                        SERVICE_STOP or SERVICE_QUERY_STATUS);
   if h_svc > 0 then
   begin
     if (ControlService(h_svc, SERVICE_CONTROL_STOP, ServiceStatus)) then
     begin
       if (QueryServiceStatus(h_svc, ServiceStatus)) then
       begin
         while (SERVICE_STOPPED <> ServiceStatus.dwCurrentState) do
         begin
           dwCheckPoint := ServiceStatus.dwCheckPoint;
           Sleep(ServiceStatus.dwWaitHint);
           if (not QueryServiceStatus(h_svc, ServiceStatus)) then
             // couldn"t check status
             break;
           if (ServiceStatus.dwCheckPoint < dwCheckPoint) then
             break;
         end;
       end;
     end;
     CloseServiceHandle(h_svc);
   end;
   CloseServiceHandle(h_manager);
 end;
 Result := (SERVICE_STOPPED = ServiceStatus.dwCurrentState);
end;


 
Alex Konshin ©   (2004-11-10 10:22) [13]

>>Alex Konshin
Спасибо за помощь, но вот 2й файл почему-то не качается :(

Хм, неудивительно, ведь он DPR...
http://home.earthlink.net/~akonshin/files/FlarpService.dpr
Вообще-то это кусок из реального проекта, потому там есть лишнее, но все-таки я думаю из него ясно, как пользоваться тем классом.


 
Alex Konshin ©   (2004-11-10 10:30) [14]

Да, если вы думаете, что я использовал стандартный отладчик для отладки сервиса, то заблуждаетесь. Я вообще не использую отладчик (и не только в случае Delphi), так как у меня частенько многопоточные приложения и надоело бороться с глюками самих отладчиков. Поэтому вся отладка по старинке - OutputDebugString и DebugView от Руссиновича (www.sysinternals.com). Он еще удобен тем, что позволяет ловить ODS удаленно - это упрощает отладку сетевых приложений.


 
Digitman ©   (2004-11-10 11:34) [15]


> У меня вот что -
> procedure THarDStarter.ServiceExecute(Sender: TService);
> begin
> //  ShowMessage("Start executing.");
>  SetPriorityClass(GetCurrentprocess,IDLE_PRIORITY_CLASS);
>  StartTimer.Enabled:=true;
>  while not Terminated do
>  begin
>    ServiceThread.ProcessRequests(False);
>  end;


зачем понижать приоритет процесса ? да еще и в Execute ?
в каком месте создается/уничтожается объект StartTimer ?
зачем нужен цикл, крайне расточительно "пожирающий" процессорное время ?


> И вот такой вот Stop


а это-то нафига ?
чем Stopped := True не устроил ?
сервис и без твоих спец.усилий будет остановлен, как только ты вернешь Stopped := True в обработчике OnStop()


 
TankMan ©   (2004-11-11 07:11) [16]

>>Digitman
Digitman ©   (10.11.04 11:34) [15]
>зачем понижать приоритет процесса ? да еще и в Execute ?
А гдеж мне его еще понижать?

>в каком месте создается/уничтожается объект StartTimer ?
Ну вообще я создал новый проект Service Application - вот там окно появляется туда и положил StartTimer.Enabled, мне нужно что бы каждые 500 мс проверялось запускать процесс или нет. Шедулер можно сказать пытаюсь писать... да и экспириенс шоб до левел апа хватило ;)

>  while not Terminated do
>  begin
>    ServiceThread.ProcessRequests(False);
>  end;
А это я взял из примера... не помню какого :(...
А что он совсем не нужен?

>> И вот такой вот Stop
>а это-то нафига ?
...ммм... :)...
Я сейчас только что  осознал что похоже это универсальный закрыватель любого сервиса? Так?... если так... то действительно... зачем оно мене - щас сделаю...

Спасибо за информацию...


 
TankMan ©   (2004-11-11 07:37) [17]

>>Digitman
Чего то я совсем не могу разобратся... -а как вызвать onstop?
ServiceStop(MyService,true) не работает
а ServiceStop(MyService,bPar)
не вызывает onstop :(
Глупость наверное спрашиваю... :)
Но хотелось бы узнать :)

А еще попутный вопрос - у меня есть форма в этом проэкте, так вот в начале она не видимая, а в трее весит иконка, из менюшки ее вызываю frmMain.showmodal, она октрывается, но почему-то не активная :(... как сделать чтобы она была на переднем плане?


 
Digitman ©   (2004-11-11 09:04) [18]


> А гдеж мне его еще понижать?


а зачем его вообще изменять ? чем он тебя не устраивает ?


> я создал новый проект Service Application - вот там окно
> появляется туда и положил StartTimer


там не просто окно появилось, там появился компонент TDataModule.

этот компонент создается в основном трэде сервис-процесса, поэтому и все компоненты, "брошенные" тобой на него, будут так же создаваться в осн.трэде, и StartTimer - не исключение.

При создании объекта класса TTimer создается невидимое окно, предназначенное для обработки сообщений WM_TIMER. Поскольку конструктор класса TTimer был вызван тобой в осн.трэде, то он и будет владельцем созданного в конструкторе окна. И события OnTimer впоследствии так же будут возбуждаться в осн.трэде.

При старте/стопе сервиса возбуждаются соотв-но события OnStart/OnStop. Возбуждаются они отнюдь не в осн.трэде, а в доп.трэде, ассоциированном с данным сервисом. В этих обработчиках ты пытаешься управлять старт/стопом таймера, обращаясь к его св-ву Enabled. Это недопустимо, поскольку таймер создан в ином трэде. При останове таймера вызывается ф-ция KillTimer(), при старте - SetTimer(), и обе эти ф-ции требуют первым параметром хэндл окна (то самое окно, которое было создано в ходе конструирования объекта), а соответствии с требованиями MS
This window must be owned by the calling thread


 
TankMan ©   (2004-11-12 09:28) [19]

>>Digitman
Не понимаю, ты говоришь "недопустимо",а ведь с таймером у меня вообще никаких проблем нет...т.е. ты предлагаешь более корректный способ(KillTimer-SetTimer)?Или так... к слову сказано?

Так и всетаки, я хотел бы узнать, как мне вызвать для сервиса OnStop? -я понял логическую "ошибку" завершения программы в моем случае...а вот onstop не могу вызвать и все...

З.Ы. Ну как мене это все надоело!!!! Заказал 2 книги по дельфи, одна из них По delphi 7 "Наиболее полное руководство" в подленнике (так и написано на обложке), 1200 страниц, вторая по Delphi5 - и НИЧЕГО про сервисы(!!!!), в обеих книгах(!),как так жить(?)..


 
Digitman ©   (2004-11-12 10:24) [20]


> TankMan ©   (12.11.04 09:28) [19]


> ты предлагаешь более корректный способ(KillTimer-SetTimer)?


Я предлагаю обращаться к методам св-вам объекта-таймера в ТОМ ЖЕ треде, в котором он был создан. Почему - я уже объяснил тебе.


> как мне вызвать для сервиса OnStop?


Никак его не надо вызывать.

Это событие будет возбуждено автоматически, когда внешний по отношению к сервису процесс подаст запрос на завершение сервиса средствами Service Control Manager.

Все что тебе нужно сделать в обработчике этого события - немедленно закруглиться по хозяйству, освободив все занятые тобой ресурсы, и вернуть Stopped := True. Сервис будет остановлен.

Если исполнение внешней команды на завершение твоего сервиса по каким-то причинам невозможно в дан.момент, просто верни Stopped := False. Сервис продолжит работу.

Если ты обрабатываешь событие OnExecute, то сервис автоматически завершит работу (будет остановлен) после завершения работы пройедуры обработки этого события, при этом событие OnStop не возникнет, если конечно же во время обработки OnExecute никто извне не дал команду на останов/завершение сервиса.
В ходе достаточно длительной обработки события OnExecute ты обязан периодически проверять флаг Terminated и немедленно закругляться по хозяйству при обнаружении условия Terminated = True (условие №1). Кр.того в этом случае ты ответственен за обязательный периодический вызов метода ProcessRequests() (условие №2). Несоблюдение или несвоевременное соблюдение условий №№ 1,2 ведет к невозможности управления работой сервиса извне либо к ощутимым задержкам исполнения команд управления сервисом извне.

Если ты НЕ назначаешь обработчик и, соотв-но, НЕ обрабатываешь событие OnExecute, то ответственность за циклический вызов метода ProcessRequests() автоматически берет на себя алгоритм в теле метода TServiceThread.Execute, в рез-те чего твой сервис будет способен немедленно реагировать на команды сервис-менеджера, которые для тебя будут выглядеть в виде возбуждения событий OnPause, OnContinue, OnStop, OnShutdown.


> З.Ы. Ну как мене это все надоело


неужели)
модуль svcmgr.pas - перед носом, а изучить происходящее там - это не для нас, мы лучше будем покупать очередной дорогущий гросбух и ждать, что вот в нем-то уж нам всю эту кухню наконец-то разжуют


 
Erik1 ©   (2004-11-12 11:44) [21]

Ты хоть один пример смотрел? По инету намоло примеров сервисов имеется. Для начала открой ..\Delphi5\Demos\Threads и посмотри как это делается. Пределай свой проект на основе треда, если бубуд вопросы тогда задавай. О то мечишся и нопонятно, что хочеш. А таймер тебе нафиг нужен, используй WaitFor... функции у них можно задать время ожидания. Вобщем учи мат. часть.


 
TankMan ©   (2004-11-15 06:44) [22]

>>Digitman ©   (12.11.04 10:24) [20]
Тааак... спасибо за информацию, конечно....
Я так понимаю что если я сделаю так:
procedure THarDStarter.ServiceExecute(Sender: TService);
begin
 SetPriorityClass(GetCurrentprocess,IDLE_PRIORITY_CLASS);
 StartTimer.Enabled:=true;
 while not Terminated do
 begin
   ServiceThread.ProcessRequests(False);
   if bStop then break;
 end;
end;
...и где-то в программе присвою bStop:=true, то программа завершится корректно?

А если я сделаю так:
procedure THarDStarter.ServiceExecute(Sender: TService);
begin
 SetPriorityClass(GetCurrentprocess,IDLE_PRIORITY_CLASS);
 StartTimer.Enabled:=true;
 while true do
 begin
   ServiceThread.ProcessRequests(False);
   if bStop then break;
 end;
end;
То программа вообще никем не завершится кроме как мной(из самой программы)?

>> З.Ы. Ну как мене это все надоело
>модуль svcmgr.pas - перед носом, а изучить происходящее там - это не для нас, мы лучше будем покупать очередной дорогущий гросбух и ждать, что вот в нем-то уж нам всю эту кухню наконец-то разжуют

Так тогда зачем вообще какие-то кники выпускают по Delphi? По твоему мнению - прочитал книжку по Pascal-ю - и дерзай - пиши проги на дельфи, т.к. это всеравно тот же паскаль. Так чтоль?

У тебя у самого скорее всего есть книги по программированию в Delphi, и скорее всего там среди всего прочего есть рассмотрение вопроса - как правильно пользоватся TImage и TTimer? А чем TServiceThread хуже? Это же такой же класс, насколько я понимаю, почему его работу не описывают?


 
Digitman ©   (2004-11-15 08:22) [23]


> Я так понимаю


в принципе ты понял правильно.


>  Так чтоль?


так или не так, но исх.тексты даны Борландом для детального изучения реализованных им алгоритмов, а не для красоты.


 
TankMan ©   (2004-11-16 13:30) [24]

Ну раз впринципе правильно, то еще раз спасибо за информацию :)
Я принял к сведению все что ты сказал. Еще раз благодарю.



Страницы: 1 вся ветка

Форум: "WinAPI";
Текущий архив: 2005.01.02;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.55 MB
Время: 0.035 c
14-1102613591
Ломброзо
2004-12-09 20:33
2005.01.02
Быстро отключить/включить картинки в IE


1-1103359985
Hyboid
2004-12-18 11:53
2005.01.02
Библиотеки интерпретатора


9-1093514453
sashuly
2004-08-26 14:00
2005.01.02
Домино


3-1100425554
Dell3r
2004-11-14 12:45
2005.01.02
Сортировка в DBGrid


14-1102897599
OlegP
2004-12-13 03:26
2005.01.02
Загадка №2





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский