Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

как заставить Service Control Manager обновить "кэш" из реестра? [Win2k, WinXP]


Ketmar ©   (2007-04-25 16:33:00) 

ситуация такая: работает сервис. другая софтина делает DeleteService(). сервис помечается на удаление, но не удаляется, пока не завершится процесс сервиса. после чего SCM запись о сервисе убивает. никакие CreateService() наново и прочие не помогают сказать SCM, что убивать никого не надо. сервис как был disabled и marked for deletion, так и остаётся. до неминуемой смерти.

в реестре за это отвечает флажок "DeleteFlag". его грохнуть можно. НО. SCM на реестр плевать, SCM хранит всю инфу в каком-то своём "кэше". есть ли хотя бы "полуштатный" способ сказать SCM'у, что "кэш" надо почистить и перечитать всё из реестра?

tnx.


clickmaker   (2007-05-02 12:32:00) [1]

Удалено модератором
Примечание: Offtopic


Rouse_   (2007-05-02 12:30:00) [2]


> потому как написать-то я написал, но глядя на разбросаные
> по коду Sleep

А нафига? У тебя же цикл сервисный крутится? Крутиться... Вот в нем периодически и делай проверку. Слипы то нафига прикручивать?


Ketmar   (2007-04-28 12:55:00) [3]

если бы у гениальных архитекторов винды ещё хватило моска сделать аналог WaitForMultipleObject() для статуса сервиса... или я с устатку и не спамши не нашёл каких-то notify-функций?

потому как написать-то я написал, но глядя на разбросаные по коду Sleep()'ы хочется аффтару открутить... в общем, что-нибудь открутить. или хотя бы подёргать за. %-)


Rouse_   (2007-04-27 23:49:00) [4]

Хм, а как ты думаешь, нафига у интербейза с фаербердом гварды написаны сервисные? :) Тоже видать малой кровью хотели обойти :)


Ketmar   (2007-04-27 22:12:00) [5]

мой сервис не держит команду "stop" (ибо нефиг %-). но дело даже не в том. процесс-то тоже могут прибить. или, например, не прибить, а просто перезагрузиться, после чего SCM грохнет запись о сервисе -- и хана.

в общем, огромный tnx за отзывы. видимо, придётся делать как думал: следилку, которая скомандует сервису помереть, если его запись пытаются удалить. и переустановит/запустит. думал обойтись "малой кровью" -- каким-то API-вызовом хитрым. увы. %-)


Rouse_   (2007-04-26 18:06:00) [6]

Да, если получиться, то придется заново дергать RegisterServiceCtrlHandlerEx повторно, для получения нового валидного описателя службы (старый то уже будет закрыт)


Rouse_   (2007-04-26 18:04:00) [7]

Нет времени проверять, да и не факт что правильно, но...

SCM будет держать флаг ERROR_SERVICE_MARKED_FOR_DELETE до тех пор, пока есть открытые описатели службы. После SetServiceStatus с флагом SERRVICE_STOPPED SCM закрывает описатель службы, вот тут имеет смысл проверить - грохнет ли он твой сервис или можно будет все-таки работать дальше... Если служба не грохнется, SCM по идее должна удалить тебя из списка служб и ты сможешь провести все действия, которые нужны.


Сергей М.   (2007-04-26 12:11:00) [8]


> Rouse_ ©   (26.04.07 11:44) [8]


У меня под винтукеем проходило.


Rouse_   (2007-04-26 11:44:00) [9]


> Success := DeleteService(hService);

Боюсь может не пройти ибо один из задокументированных кодов возврата стоит "ERROR_SERVICE_MARKED_FOR_DELETE"


Сергей М.   (2007-04-26 10:52:00) [10]


> Ketmar ©   (25.04.07 18:47) [4]


Посмотри на wasm.ru статью и пример по теме "Монитор создания и уничтожения процессов" - там как раз реализована манипуляция вр еменным созданием/уничтожением сервиса для запуска/останова драйвера режима ядра.

Вот (для облегчения анализа) Паскаль-портация ключевых фрагментов из того примера:


// старт системы слежения
procedure StartMonitor;
var
 hSCM, hService: THandle;
 idThread, BytesReturned: DWord;
 State: TServiceStatus;
begin
 if Started then Exit;
 CheckDrvFileExists; //если файла драйвера еще нет на диске в сист.каталоге ОС, создадим его из своего ресурса
 hSCM := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
 Win32Check(hSCM <> 0);
 try
   hService := CreateService(hSCM, 'ProcessMon', 'NT process Montor',
                             SERVICE_START or SERVICE_STOP or SERVICE_QUERY_STATUS or _DELETE,
                             SERVICE_KERNEL_DRIVER,
                             SERVICE_DEMAND_START,
                             SERVICE_ERROR_IGNORE,
                             PChar(DrvName),
                             nil, nil, nil, nil, nil);
   if (hService = 0) and (GetLastError = ERROR_SERVICE_EXISTS) then
     hService := OpenService(hSCM, 'ProcessMon', SERVICE_ALL_ACCESS);
   Win32Check(hService <> 0);
   try
     Win32Check(QueryServiceStatus(hService, State));
     if State.dwCurrentState = SERVICE_STOPPED then
       Win32Check(StartService(hService, 0, SvcStartParams));
     with WaitParams do
     try
       hDevice := CreateFile(sDeviceName,
                             GENERIC_READ or GENERIC_WRITE,
                             0, nil, OPEN_EXISTING, 0, 0);
       Win32Check(hDevice <> 0);
       try
         hEvent := CreateEvent(nil, FALSE, FALSE, nil);
         Win32Check(hEvent <> 0);
         try
           ExitNow := False;
//стартуем следящий трэд
           hWaitThread := BeginThread(nil, 0, @WinEtkaWatchDog, @WaitParams, 0, idThread);
           Win32Check(hWaitThread <> 0);
//подождем пока трэд создаст очередь win-сообщений
           while not PostThreadMessage(idThread, WM_USER, 0, 0) do Sleep(0);
           try
//скомандуем устр-ву начать слежение за процессами
             Win32Check(DeviceIoControl(hDevice,
                                         IOCTL_SET_NOTIFY,
                                         @hEvent,
                                         SizeOf(hEvent), nil, 0, BytesReturned, nil)
                       );
             Started := True;
           except
             ExitNow := True;
             SetEvent(hEvent);
             WaitForSingleObject(hWaitThread, INFINITE);
             CloseHandle(hWaitThread);
             raise;
           end;
         except
           CloseHandle(hEvent);
           raise;
         end;
       except
         CloseHandle(hDevice);
         raise;
       end;
     except
       ControlService(hService, SERVICE_CONTROL_STOP, State);
       raise;
     end;
   finally
      DeleteService(hService);
     CloseServiceHandle(hService);
   end;
 finally
   CloseServiceHandle(hSCM);
 end;
end;

// останов системы слежения

procedure StopMonitor;
var
 hSCM, hService: THandle;
 BytesReturned: DWord;
 State: TServiceStatus;
 Success: Boolean;
begin
 if Started then
   with WaitParams do
   begin
     ExitNow := True;
     SetEvent(hEvent);
     WaitForSingleObject(hWaitThread, INFINITE);
     CloseHandle(hWaitThread);
     Win32Check(DeviceIoControl(hDevice, IOCTL_REMOVE_NOTIFY, nil, 0, nil, 0, BytesReturned, nil));
     CloseHandle(hEvent);
     CloseHandle(hDevice);
     hSCM := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
     hService := OpenService(hSCM, 'ProcessMon', SERVICE_STOP or _DELETE);
     Success := ControlService(hService, SERVICE_CONTROL_STOP, State);
     Success := DeleteService(hService);
     CloseServiceHandle(hService);
     CloseServiceHandle(hSCM);
     Started := False;
   end;
end;


У меня под Винтукеем это работало, хотя проблема действительно имеет место быть.


Германн   (2007-04-26 01:41:00) [11]

Удалено модератором
Примечание: Offtopic


Leonid Troyanovsky   (2007-04-25 22:16:00) [12]


> Ketmar ©   (25.04.07 18:47) [4]

Боюсь соврать, но Alex Fedotov, кажись обсуждал проблему
кеширования либо в своей статье, либо просто по форуму rsdn winapi
(А может это был Танненбаум).
Уточнять мне влом, бо скоро ФУТБОЛ!!

--
Regards, LVT.


Ketmar   (2007-04-25 18:47:00) [13]

да так сейчас и пишу (сервис мой %-). но как-то оно не того -- помирать каждый раз. хотелось бы без смертей обойтись. %-)

мои эксперименты со всякими разными последовательностями пинков SCM результата не дали, увы. но как-то же он кэшит всё по CreateService(), например? правда, не факт, что эта машинерия общедоступна. и так неохота (да и времени нет) ковыряться там отладчиком...


Rouse_   (2007-04-25 18:08:00) [14]

Ааа, так тебе вернуть его нужно :)
Ну тут нужно поэсперементировать... так даже с наскока не скажу :)

Кстати, а сервис твой? Ежели твой - то периодически проверяй себя на зарегеность, если кно снял, завершайся и воостанавливай себя на законное место :)


Ketmar   (2007-04-25 18:05:00) [15]

потому что "другая софтина" -- это юзер с FAR'ом, например. %-)

Розыч, если бы всё было решаемо такими методами, я бы не заморачивался подобными вопросами. суть тут в том, что "полугрохнутый" кривыми руками сервис надо вернуть на место. к сожалению, вариант "починить кривые руки" не проходит... %-(


Rouse_   (2007-04-25 17:56:00) [16]

А почемубы "другой софтине" сначала не дать команду сервису на остановку, после чего дождаться его завершения и только после этого вызвать DeleteService? И не нужно будет изобретать велосипед с перечитыванием кэша...


Наверх

Титульная страница Поиск, карта сайта Написать письмо