|
Вопрос # 279/ вопрос открыт / |
|
Стоит задача создать сервис, который при старте запустит другое приложение через СОМ. И чтоб это приложение висело в памяти до остановки службы.
Дайте что-то почитать про использование обработчиков OnExecute,OnStart etc.
Приложение: Переключить в обычный режим-
-
- RezultConnect := 0;
- OdnaC := CreateOLEObject('V77S.Application');
- BaseAdres := 'D:!Balabasy!WorkProphotoSQLBase';
- UserName := 'worm';
- UserPwd := 'infinity';
- try
- RezultConnect := OdnaC.initialize(OdnaC.rmtrade,'/d'+BaseAdres+'
/n '+UserName+' /p '+UserPwd,'NO_SPLASH_SHOW');
- Except
- exit;
- end;
-
- try
- Gdem:=OdnaC.EvalExpr('glOnline()');
- Except
- exit;
- end;
-
 |
Вопрос задал: Вакуленко (статус: Посетитель)
Вопрос отправлен: 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);
Мини-форум вопроса
Всего сообщений: 10; последнее сообщение — 29 января 2007, 15:12; участников в обсуждении: 3.
|
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 (статус: Посетитель), 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 (статус: Посетитель), 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). Или не пустым но с какими то вычислениями. Тестил на записи текста в файл - все ок.
А вот с СОМ никак =(
|
|
fd_coder (статус: Посетитель), 27 января 2007, 08:51 [#9]:
включи интерактивное взаимодействие в свойствах сервиса (Interactive = True, по умолчанию оно отключено)
Позже попробую в отладке и мож еще че-нить подскажу
|
|
fd_coder (статус: Посетитель), 29 января 2007, 15:12 [#10]:
попробуй свой код (до While) поместить в другой поток (или таймер), а в процедуре старт или креате запускать соответственно поток (или таймер) на выполнение
var
BaseAdres:string;
UserName:string;
...
While not terminated do
begin
ServiceThread.ProcessRequests(True);
end;
...
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|