Работа в режиме службы

Clarion, Clarion 7

Модератор: Дед Пахом

Правила форума
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
Ответить
Malex
Посетитель
Сообщения: 26
Зарегистрирован: 16 Март 2006, 14:59
Откуда: Крым

Работа в режиме службы

Сообщение Malex »

Программа на Кларион, работает в трее на Windows 2003 server. Как организовать ее работу как служба Windows? Давно встречал статью про какуюто утилиту, кот. позволяла это делать. Может кто знает ?
Аватара пользователя
Admin
Администратор
Сообщения: 4010
Зарегистрирован: 05 Июль 2005, 15:59
Откуда: Хабаровск
Благодарил (а): 53 раза
Поблагодарили: 33 раза
Контактная информация:

Сообщение Admin »

Смотри: http://www.authord.com/Clarion/
Там есть: http://www.passwordsmax.com/winapitk.zip
в нем смотри: Run an application as an NT Service (32-bit, NT).
Рай совершает ошибки ничуть не реже чем ад. Просто у него хорошая пресса
Malex
Посетитель
Сообщения: 26
Зарегистрирован: 16 Март 2006, 14:59
Откуда: Крым

Сообщение Malex »

Спасибо! Попробовал на Win XP, работает как часы. Думаю на Win 2003 serv. проблем не будет.
seawolf
Старожил
Сообщения: 217
Зарегистрирован: 08 Июль 2005, 11:23
Откуда: St. Petersburg

Re: Работа в режиме службы

Сообщение seawolf »

Вытащил на свет этот старый пост со старым кодом. Поскольку копнул службы решил покопаться внутри (пока есть вермя). InstallService и RemoveService здесь вроде все отрабатывает.
Пытаюсь запускать приложение как сервисы (как свое так и заведомо работающие).
Почему-то StartServiceCtrlDispatcher все время выдает 0. Его таблицу заполняем адресом присвоенного именем ServiceName. Почему-то сгенеренный код делает присваивание ServiceName='ServiceMain' и до вызова ServiceMain процедуры дело не доходит. В чем тут заковыка могет быть? Свое Приложение не в трее и не консоль, просто без окна.


StartServiceMain PROCEDURE

ServiceTable GROUP,PRE(LOC)
ServiceName UNSIGNED ! ADDRESS() of Service Name
ServiceProc UNSIGNED ! ADDRESS() of Main Service Proc
EndServiceName SIGNED(0) ! Null to indicate end
EndServiceProc SIGNED(0) ! Null to indicate end
END

CODE

ServiceName='ServiceMain'
LOC:ServiceName = ADDRESS(ServiceName)
LOC:ServiceProc = ADDRESS(ServiceMain)

IF StartServiceCtrlDispatcher(ADDRESS(ServiceTable))
ELSE
MESSAGE(GetAPIError() & '.<13>Cannot start service.','Error')
.


ServiceMain PROCEDURE(pParam1,pParam2)
LOC_ThreadID ULONG

CODE


hServiceStatus=RegisterServiceCtrlHandler(ADDRESS(ServiceName),ADDRESS(ServiceHandler))
IF ~hServiceStatus
MESSAGE(GetAPIError() & '.<13>Cannot register service handler.','Error')
.
CurrentState = SERVICE_RUNNING
SCResult = SendStatustoSCM(SERVICE_RUNNING, NO_ERROR, 0, 1, 1000)
ServiceRunning=1
GLO:ServiceStatus = ServiceRunning + 2 * ServicePaused
! Main - need to call as a new thread to operate properly.
IF ~CreateThread(0,0,ADDRESS(main),0,0,LOC_ThreadID)
DO ServiceStop
.
DO ServiceStop
seawolf
Старожил
Сообщения: 217
Зарегистрирован: 08 Июль 2005, 11:23
Откуда: St. Petersburg

Re: Работа в режиме службы

Сообщение seawolf »

Весь этот старый пример прекрасно собирается и работает под clarion5. Под 6 нет!
Аватара пользователя
WadimZapara
Активист
Сообщения: 181
Зарегистрирован: 11 Июнь 2008, 12:11
Откуда: Тамбов

Re: Работа в режиме службы

Сообщение WadimZapara »

Почему-то StartServiceCtrlDispatcher все время выдает 0
1) Интересно, а как происходит запуск ?
Ведь успех-то может быть только при запуске от SCM - именно как службы из диспетчера служб или там NET START... и т.д..
И что при этом говорит GetLastError() - а он-то многое расскажет!
2) А MESSAGE-то появляется ? А служба-то уже зарегистрирована в SCM ? И именно, как взаимодействующая с рабочим столом.
3) А как объявлена переменная ServiceName (я про атрибут STATIC и тип CSTRING)
4) А что у тебя ServiceHandler...
5) А что делает ServiceStop routine ...
...
В общем - мало информации об условиях неработоспособности :roll:
Компьютер имеет то преимущество перед мозгом, что им пользуются...
seawolf
Старожил
Сообщения: 217
Зарегистрирован: 08 Июль 2005, 11:23
Откуда: St. Petersburg

Re: Работа в режиме службы

Сообщение seawolf »

Ну собственно вот исходник практически не писаный самим (его сгенерил шаблон в C5). Имя сервиса а прописал.
GetLastError() возвращает 0. Запуск через sc - 1067. Сервис уже инсталлирован (InstallServcie). Sc query tgtmsvc отвечает что такой есть но пока не запущен. Попытка сделать start и вываливается MESSAGE(GetAPIError() & '.<13>Cannot start service.','Error'). Все тоже самое на C5 сходу работает.
Вложения
vs_ntsrv.clw
(68.63 КБ) 535 скачиваний
Аватара пользователя
WadimZapara
Активист
Сообщения: 181
Зарегистрирован: 11 Июнь 2008, 12:11
Откуда: Тамбов

Re: Работа в режиме службы

Сообщение WadimZapara »

Оформлено как DLL ?
Компьютер имеет то преимущество перед мозгом, что им пользуются...
seawolf
Старожил
Сообщения: 217
Зарегистрирован: 08 Июль 2005, 11:23
Откуда: St. Petersburg

Re: Работа в режиме службы

Сообщение seawolf »

Нет это просто по include затащен в проект. Сам проект прога exe. Без интерфейса, раз в 20 секунд делает опрос pop3 ящика и разбор чего там есть. Под 5 версией работает без проблем. Под 6 просто служба не стартует и все. Вот если руки дойдут под 7 посмотрю.
Аватара пользователя
WadimZapara
Активист
Сообщения: 181
Зарегистрирован: 11 Июнь 2008, 12:11
Откуда: Тамбов

Re: Работа в режиме службы

Сообщение WadimZapara »

А что же у тебя является основным кодом EXE-шника ? Ответь для ясности. Ща смотрю твой пример. Соображения есть... Изложу чуть позже.
И ещё - условия испытаний одинаковы (Под одной и той же операционкой, с одинаковыми ли правами запускаешь) ?
Запускаешь сервис с помощью чего (NET START / SC.EXE / SEVICES.MSC) ?

P.S. GetLasError()=1067 - The process terminated unexpectedly. (Процесс завершился неожиданно)
Компьютер имеет то преимущество перед мозгом, что им пользуются...
Аватара пользователя
WadimZapara
Активист
Сообщения: 181
Зарегистрирован: 11 Июнь 2008, 12:11
Откуда: Тамбов

Re: Работа в режиме службы

Сообщение WadimZapara »

Думаю, в основном - всё идёт от иной THREAD-модели в C6 по сравнению с C5. И поэтому - некоторые процедуры (см.ниже) завершаются, а система продолжает работать с их переменными, которые уже выгружены из памяти.
Вероятно основной код программы состоит из вызова (или после обработки параметров заканчивается вызовом) StartServiceMain

Объяви переменные глобально и попробуй:
ServiceTable GROUP из процедуры StartServiceMain
LOC:SERVICE_STATUS LIKE(SERVICE_STATUS) из функции SendStatusToSCM

ежели не будет изменений -
не завершай процедуру ServiceMain после запуска нового потока, а отправь его в спячку до возникновения какого-то события.
То есть после строк
IF ~CreateThread(0,0,ADDRESS(Main),0,0,LOC_ThreadID)
DO ServiceStop
.
допиши типа:

Код: Выделить всё

    !Создаём системное событие для сигнализации необходимости останова
    ghSvcStopEvent = CreateEvent(0,       | ! default security attributes
                                 TRUE,    | ! manual reset event
                                 FALSE,   | ! not signaled
                                 0)         ! no name
    If ghSvcStopEvent Then  ! успешно создан объект "событие"
      SendStatustoSCM( SERVICE_RUNNING, NO_ERROR, 0, 1, 1000 )  ! Отметить для SCM: "сервис в работе"
      Loop
        ! Вместо работы - просто ожидаем, когда нам скажут "STOP" - ждём возникновения события <ghSvcStopEvent>
        WaitForSingleObject(ghSvcStopEvent, INFINITE)
        Break
      End
    End
    SendStatustoSCM( SERVICE_STOPPED, NO_ERROR, 0, 1, 1000 )    ! Отметить для SCM: "сервис остановлен"
а в обработке controlCode = SERVICE_CONTROL_STOP в процедуре ServiceHandler укажи (взамен твоего), а также - если нужно при ином условии завершения, например, перед оператором RETURN процедуры MAIN:

Код: Выделить всё

      SendStatustoSCM( SERVICE_STOP_PENDING, NO_ERROR, 0, 1, 1000)      ! изменить состояние на "начат процесс останова"
      SetEvent(ghSvcStopEvent)          ! взвести(активировать) событие <ghSvcStopEvent> (будет принято в ServiceMain)
где ghSvcStopEvent - глобально объявлено, как:
ghSvcStopEvent HANDLE ! Handle события StopEvent
---------------------------------------------------
И ещё, для подключения к Service Control Manager
MSDN ПИШЕТ:
The OpenSCManager function establishes a connection to the service control manager on the specified computer and opens the specified service control manager database.
SC_HANDLE OpenSCManager(
LPCTSTR lpMachineName,
LPCTSTR lpDatabaseName,
DWORD dwDesiredAccess
);
Parameters
lpMachineName [in] Pointer to a null-terminated string that specifies the name of the target computer. If the pointer is NULL or points to an empty string, the function connects to the service control manager on the local computer.
lpDatabaseName [in] Pointer to a null-terminated string that specifies the name of the service control manager database to open. This parameter should be set to SERVICES_ACTIVE_DATABASE. If it is NULL, the SERVICES_ACTIVE_DATABASE database is opened by default.
dwDesiredAccess [in] Access to the service control manager. For a list of access rights, see Service Security and Access Rights.
Before granting the requested access rights, the system checks the access token of the calling process against the discretionary access-control list of the security descriptor associated with the service control manager.
The SC_MANAGER_CONNECT access right is implicitly specified by calling this function.

ПРИ ЭТОМ, СОДЕРЖИТСЯ в advapi32.dll В ДВУХ ВАРИАНТАХ: OpenSCManagerA, OpenSCManagerW
-----------------------------------
ПОЭТОМУ МОЁ ОБЪЯВЛЕНИЕ:
OpenSCManager( <*CString lpMachineName>, <*CString lpDatabaseName>, DWORD dwDesiredAccess ), SC_HANDLE, Pascal, Raw, Dll, Name('OpenSCManagerA')
И МОИ ВЫЗОВЫ:
hSCM = OpenSCManager( , , STANDARD_RIGHTS_WRITE + SC_MANAGER_CONNECT + SC_MANAGER_CREATE_SERVICE ) ! для инсталляции сервиса
hSCM = OpenSCManager( , , STANDARD_RIGHTS_READ + SC_MANAGER_CONNECT + SC_MANAGER_ENUMERATE_SERVICE ) ! для перечисления сервисов
hSCM = OpenSCManager( , , STANDARD_RIGHTS_READ + SC_MANAGER_CONNECT ) ! для подключения

Последнее поможет на случай, если ServicesDatabaseName='ServicesActive' для SCM непонятно.
Компьютер имеет то преимущество перед мозгом, что им пользуются...
seawolf
Старожил
Сообщения: 217
Зарегистрирован: 08 Июль 2005, 11:23
Откуда: St. Petersburg

Re: Работа в режиме службы

Сообщение seawolf »

Прошу прощение за задержку, только вернулся из поездки. Основной код exe это как и предполагалось вызов StratMainService. Переобъявление в голабальные переменные очереди Loc не помогло. Остальное буду смотреть, после чего отпишусь.
Аватара пользователя
WadimZapara
Активист
Сообщения: 181
Зарегистрирован: 11 Июнь 2008, 12:11
Откуда: Тамбов

Re: Работа в режиме службы

Сообщение WadimZapara »

Да, HANDLE и SC_HANDLE - это UNSIGNED.

Кроме того, нужно проверить и иметь в виду следующее:
1. Переменные, которые используются в разных потоках обязательно должны использоваться через систему семафора/мьютекса/события, чтобы более одного THREAD'а не имело возможности доступа к переменной.
2. К таким же переменным относятся и области данных, адреса которых передаются в CALLBACK-функции Windows.
3. Есть такой нюанс (я натыкался):
- в теле CLARION-процедуры делаешь какой-то вызов Windows-функции, предавая ей в качестве параметров локальные переменные этой CLARION-процедуры
- после это завершаешь CLARION-процедуру
- РЕЗУЛЬТАТ ОШИБКА ДОСТУПА К ПАМЯТИ
= Причина: Windows-функция ещё в процессе исполнения, а кларион уже чистит выделенную твоей процедуре память (и под код, и под переменные).
(у меня это была передача файлов по FTP с CallBack-процедурой для отслеживания процесса; когда я выяснял, что все байты файла уже переданы - я давал команду по отключению CallBack-процедуры, закрывал все Handle-ы и завершал свою Кларион-процедуру, а в это время - как выяснилось, в CallBack-процедуру, а точнее в то место памяти, где она была ранее распределена кларионом, который уже провёл "зачистку", - продолжали поступать управляющие данные протокола FTP).
Выход: А) нужно, по-возможности, убеждаться в завершении работы Windows-функции, Б) такие переменные должны быть STATIC (если не получается А)
Компьютер имеет то преимущество перед мозгом, что им пользуются...
Ответить