Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 279

/ вопрос открыт /

Стоит задача создать сервис, который при старте запустит другое приложение через СОМ. И чтоб это приложение висело в памяти до остановки службы.
Дайте что-то почитать про использование обработчиков OnExecute,OnStart etc.

Приложение:
  1.  
  2.  
  3. RezultConnect := 0;
  4. OdnaC := CreateOLEObject('V77S.Application');
  5. BaseAdres := 'D:!Balabasy!WorkProphotoSQLBase';
  6. UserName := 'worm';
  7. UserPwd := 'infinity';
  8. try
  9. RezultConnect := OdnaC.initialize(OdnaC.rmtrade,'/d'+BaseAdres+' /n '+UserName+' /p '+UserPwd,'NO_SPLASH_SHOW');
  10. Except
  11. exit;
  12. end;
  13.  
  14. try
  15. Gdem:=OdnaC.EvalExpr('glOnline()');
  16. Except
  17. exit;
  18. end;
  19.  


Вакуленко Вопрос ожидает решения (принимаются ответы, доступен мини-форум)

Вопрос задал: Вакуленко (статус: Посетитель)
Вопрос отправлен: 22 января 2007, 22:19
Состояние вопроса: открыт, ответов: 2.

Ответ #1. Отвечает эксперт: Вадим К

Вы используете COM объекты, поэтому ваше приложение должно сообщить операционной системе об этом. Делается это вызовом процедуры CoInitialize в самом начале вашей проги. Это общеизвестная проблема.
По поводу почитать могу порекомендовать только MSDN. В часности, замечу, что обработчик OnStart должен быть как можно быстр. Если он будет выполнятся долго, то Операционная система вправе "прибить" ваш сервис. И во вторых, непытайтесь делать активное взаиводействие с пользователем - типа MessageBox'ов - для этого сервис должен быть интерактивным и соответственно накладываются определённые особенности.

Ответ отправил: Вадим К (статус: Академик)
Время отправки: 23 января 2007, 01:51

Ответ #2. Отвечает эксперт: Лукьяненко Алексей Валериевич

Здравствуйте, Вакуленко!

По поводу COM вам рассказали, добавлю лишь, что при окончании работы нужно вызвать CoUninitialize. Эту пару вызовов необходимо делать для каждого потока, использующего COM. Приложение с сервисом использует 2 потока - поток запустивший сервис (события OnStart, OnStop, OnShutdown) и собственно поток сервиса (OnExecute).
Реализация вашего кода, если это сервис, должна быть записана в обработчике OnExecute. При этом нужно помнить:
1. При выходе из OnExecute сервис завершает свою работу и останавливается.
2. Чтобы сервис мог реагировать на системные ссобщения (типа остановить, перезапустить и др.) в коде сервиса нужно периодически вызывать ServiceThread.ProcessRequests(Wait: Boolean);
Параметр Wait указывает, ждать ли сообщений системы, или только обработать то, что есть в очереди и вернуть управление вызывающему.
В Вашем случае для организации работы сервиса после запуска COM-серверов нужно создать бесконечный цикл, вызывающий ServiceThread.ProcessRequests(True);

Ответ отправил: Лукьяненко Алексей Валериевич (статус: 1-ый класс)
Время отправки: 23 января 2007, 11:46
Оценка за ответ: 5


Мини-форум вопроса

Всего сообщений: 10; последнее сообщение — 29 января 2007, 15:12; участников в обсуждении: 3.
fd_coder

fd_coder (статус: Посетитель), 23 января 2007, 00:02 [#1]:

поищи "Написание сервисов на Delphi"

знаю точно, что сервис надо инсталить еще тогда он будет работать, но точно сейчас не могу текст дать (он у меня на работе остался)
Вакуленко

Вакуленко (статус: Посетитель), 24 января 2007, 21:42 [#2]:

Всем спасибо за ответы. Но к сожелению проблема есче существует. Дело в том, сервис всеравно прибивается виндой. Кстати COM создается(видно в таск менеджере).
вот тело OnExecute (может я делаю что то изза чего винда прибивает сервис?):
CoInitializeEx(NIl,COINIT_APARTMENTTHREADED);

While true do
begin
OdnaC := CreateOLEObject('V77S.Application');

BaseAdres := 'D:\!Balabasy\!Work\Prophoto\SQLBase';
UserName := 'worm';
UserPwd := 'infinity';
RezultConnect := OdnaC.initialize(OdnaC.rmtrade,'/d'+BaseAdres+' /n '+UserName+' /p '+UserPwd,'NO_SPLASH_SHOW');
Gdem:=OdnaC.EvalExpr('glOnline()');

Sleep(1000);
ServiceThread.ProcessRequests(True);
end;

CoUninitialize;
fd_coder

fd_coder (статус: Посетитель), 25 января 2007, 01:30 [#3]:

я с сокетами работал (писал что-то типа радмина)

у меня текст такой в OnExecute
while not terminated do begin
ServiceThread.ProcessRequests(True);
end;
Вакуленко

Вакуленко (статус: Посетитель), 25 января 2007, 02:36 [#4]:

наверное так будет правильнее. но фактом остается то что при старте сервис прибивается. Скажите кто знает как отладить код выполняющийса в в сервисном приложении?

CoInitializeEx(NIl,COINIT_APARTMENTTHREADED);

OdnaC := CreateOLEObject('V77S.Application');
BaseAdres := 'D:\!Balabasy\!Work\Prophoto\SQLBase';
UserName := 'worm';
UserPwd := 'infinity';
RezultConnect := OdnaC.initialize(OdnaC.rmtrade,'/d'+BaseAdres+' /n '+UserName+' /p '+UserPwd,'NO_SPLASH_SHOW');
Gdem:=OdnaC.EvalExpr('glOnline()');

While not terminated do
begin
ServiceThread.ProcessRequests(True);
end;

CoUninitialize;
Лукьяненко Алексей Валериевич

Лукьяненко Алексей Валериевич (статус: 1-ый класс), 25 января 2007, 10:40 [#5]:

Отладка сервиса:
1. Открываете проект в Делфи, компилируете его
2. Устанавливаете сервис (имя.exe /install)
3. Открываете оснастку "Службы" (Services) в панели управления-средства администрирования, ищите свой сервис, стартуете его
4. в Делфи Run-Attach to process... и в окне выбираете процесс сервиса

А насчет прибивания ОС сервиса - а вы его регистрировали в системе (п. 2), или пытаетесь запустить как обычное приложение?
fd_coder

fd_coder (статус: Посетитель), 25 января 2007, 15:47 [#6]:

Я так делал:
1. Жми Ctrl-F9.
2. Потом откомпилированный файл запускай из команндной строки:
имяфайла.exe /INSTALL /SILENT
этим ты установишь сервис в систему.
3. Потом в менеджере сервисов запускаешь свою службу.
4. Всё

Пункт 3 - изврат, поэтому юзай эту функцию в событии AfterInstall для TService:


function StartSrv(aMachine, aServiceName: string): boolean;
var
h_manager,h_svc: SC_Handle;
svc_status: TServiceStatus;
Temp: PChar;
dwCheckPoint: DWord;
begin
svc_status.dwCurrentState := 1;
h_manager := OpenSCManager(PChar(aMachine), nil, SC_MANAGER_CONNECT);
if h_manager > 0 then begin
h_svc := OpenService(h_manager, PChar(aServiceName), SERVICE_START or SERVICE_QUERY_STATUS);
if h_svc > 0 then begin
temp := nil;
if (StartService(h_svc,0,temp)) then
if (QueryServiceStatus(h_svc,svc_status)) then begin
while (SERVICE_RUNNING <> svc_status.dwCurrentState) do begin
dwCheckPoint := svc_status.dwCheckPoint;
Sleep(svc_status.dwWaitHint);
if (not QueryServiceStatus(h_svc,svc_status)) then break;
if (svc_status.dwCheckPoint < dwCheckPoint) then break;
end;
end;
CloseServiceHandle(h_svc);
end;
CloseServiceHandle(h_manager);
end;
Result := SERVICE_RUNNING=svc_status.dwCurrentState;
end;

или выложи полный исходник и кинь ссылку, в отладке посмотрим
Вакуленко

Вакуленко (статус: Посетитель), 26 января 2007, 02:21 [#7]:

Лукьяненко Алексей Валериевич (статус: 1-ый класс), 25.01.2007, 10:40:
Сервис регистрировал. Под словом ОС прибивает я имел ввиду это сообщения возникающее при запуске: "Некоторые службы прикращают свою работу если им нечего делать .... ".
Соедует добавить что код работает в обычном приложении. И что сервис нормально выполняется если OnExecute оставить пустым (только с циклом в котором ServiceThread.ProcessRequests(True). Или не пустым но с какими то вычислениями. Тестил на записи текста в файл - все ок.
А вот с СОМ никак =(
Вакуленко

Вакуленко (статус: Посетитель), 26 января 2007, 03:00 [#8]:

fd_coder (статус: Посетитель), 25.01.2007, 15:47:
Полглсьбю исходник:
http://www.rapidshare.ru/154527
fd_coder

fd_coder (статус: Посетитель), 27 января 2007, 08:51 [#9]:

включи интерактивное взаимодействие в свойствах сервиса (Interactive = True, по умолчанию оно отключено)
Позже попробую в отладке и мож еще че-нить подскажу
fd_coder

fd_coder (статус: Посетитель), 29 января 2007, 15:12 [#10]:

попробуй свой код (до While) поместить в другой поток (или таймер), а в процедуре старт или креате запускать соответственно поток (или таймер) на выполнение

var
BaseAdres:string;
UserName:string;
...
While not terminated do
begin
ServiceThread.ProcessRequests(True);
end;
...

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 11:54
Выполнено за 0.03 сек.