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

Вниз

Не могу остановить свой сервис   Найти похожие ветки 

 
novill ©   (2006-06-23 10:48) [0]

Написал сервис по описанию в хелпе.

При попытке остановить процесс Винда выдает ошибку: "не удалось остановить службу. Эта служба не возвращала код ошибки. Возможно это внутренняя ошибка Windows или службы."


После этого службу нельзя удалить (uninstall). Windows говорит что пометила ее на удаление, но до перезагрузки служба висит: ни запустить , ни остановить.

unit ServU;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs,
 DB, IBCustomDataSet, IBQuery, IBDatabase;

type
 TDS = class(TService)
   procedure ServiceExecute(Sender: TService);
 private
   { Private declarations }
 public
   function GetServiceController: TServiceController; override;
   { Public declarations }
 end;

var
 DS: TDS;

implementation

uses mainU;
{$R *.DFM}

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

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

procedure TDS.ServiceExecute(Sender: TService);

begin
    while not Self.Terminated do
     begin
      {мои процедуры}
     end;
end;

end


 
Сергей М. ©   (2006-06-23 10:56) [1]

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


 
novill ©   (2006-06-23 11:03) [2]

Добавил:

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

Та же ошибка...


 
Сергей М. ©   (2006-06-23 11:18) [3]

Тогда показывай, что творится у тебя в

{мои процедуры}

Кстати, Self не нужен - Terminated является св-вом самого TService.


 
novill ©   (2006-06-23 11:36) [4]

Там творилось много чего. (Почтовый робот).
Но оказалось, что остановить невозможно сервис даже с таким телом.

procedure TDownloadService.ServiceExecute(Sender: TService);
var statfile:Text;
begin
  AssignFile(statfile,"event.log");
    while not Self.Terminated do
     begin
       Append(statfile);
       Writeln(statfile,DateTimeToStr(Now));
       Flush(statfile);
       SleepEx(5000,true);
     end;
  CloseFile(statfile);
end;


 
Сергей М. ©   (2006-06-23 11:39) [5]


> оказалось, что остановить невозможно сервис даже с таким
> телом.
>


Потому что вызов метода TServiceThread.ProcessRequests() у тебя напрочь отсутствует. А он ключевой во всей этой сервисной "кухне".


 
novill ©   (2006-06-23 11:50) [6]

спасибо

Добавил. Ошибка все равно иногда валится, но служба останавливается.


 
novill ©   (2006-06-23 11:52) [7]

Строчку добавил такую

      ServiceThread.ProcessRequests(False);

Может, вы знаете, почему доступа к IB из сервиса может не быть?


 
Сергей М. ©   (2006-06-23 12:01) [8]


> почему доступа к IB из сервиса может не быть?


Об этом тебе скажет код ошибки, возвращенный ф-цией, осуществляющей "доступ"


 
Сергей М. ©   (2006-06-23 12:09) [9]

И, кстати, причем здесь WinAPI ?


 
novill ©   (2006-06-23 12:38) [10]


> Сергей М. ©   (23.06.06 12:09) [9]
> И, кстати, причем здесь WinAPI ?

Не знаю, я в основную писал, кто-то из админов перекинул


 
Игорь Шевченко ©   (2006-06-23 12:39) [11]


> И, кстати, причем здесь WinAPI ?


Если кто скажет, что проблемы с сервисами не относятся к тематике конференции "работа с системой", я перенесу ветку обратно в "основную"


 
novill ©   (2006-06-23 12:45) [12]

Тогда уже лучше перименовать "WinApi WinAPI" в "Система(Winapi)"


 
Сергей М. ©   (2006-06-23 12:48) [13]


> novill ©   (23.06.06 12:45) [12]


Ты на [8] отреагировал ?


 
novill ©   (2006-06-23 13:41) [14]

ESockError
Connection Failed


 
novill ©   (2006-06-23 13:48) [15]

При этом та же функция доступа из оконного приложения работает исправно.


 
Сергей М. ©   (2006-06-23 14:04) [16]

Сервис с какими правами запущен ? От имени какого пользователя ?


 
novill ©   (2006-06-23 14:20) [17]

Сначала запускал как локальную службу, потом создал запись с админскими правами и запустил от ее имени - та же история :(


 
Сергей М. ©   (2006-06-23 14:25) [18]

Какие компоненты доступа к IB используешь ?


 
novill ©   (2006-06-23 17:34) [19]

С доступом оказывается я ошибался - я локально подключался, а сервисы только через сеть работают, надо было через 127.0.0.1

Но  не могу понять, почему выскакивает ошибка при останове сервиса :(
При попытки останова сервиса, процедура ServiceStop не выполняется, несмотря на то что повешена на событие onStop.

unit Unit1;
interface
uses  Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs;
type
 TService1 = class(TService)
   procedure ServiceExecute(Sender: TService);
   procedure ServiceStop(Sender: TService; var Stopped: Boolean);
   procedure ServiceStart(Sender: TService; var Started: Boolean);
   procedure ServiceShutdown(Sender: TService);
 public
   function GetServiceController: TServiceController; override;
 end;
var
 Service1: TService1;
implementation
{$R *.DFM}
procedure ServiceController(CtrlCode: DWord); stdcall;
begin
 Service1.Controller(CtrlCode);
end;

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

procedure TService1.ServiceExecute(Sender: TService);
var statfile:Text;
begin
  AssignFile(statfile,"event.log");
    while not Self.Terminated do
     begin
     ServiceThread.ProcessRequests(False);
     Append(statfile); Writeln(statfile,DateTimeToStr(Now));
     Flush(statfile);
     SleepEx(5000,False);
     end;
  CloseFile(statfile);
end;

procedure TService1.ServiceStop(Sender: TService; var Stopped: Boolean);
var statfile:Text;
begin
 Stopped:=true;

 AssignFile(statfile,"event.log");
 Append(statfile);
 Writeln(statfile,"ServiceStop(");
 Flush(statfile);
 CloseFile(statfile);

end;

procedure TService1.ServiceStart(Sender: TService; var Started: Boolean);
var statfile:Text;
begin
 AssignFile(statfile,"event.log");
 Append(statfile);
 Writeln(statfile,"ServiceStart(");
 Flush(statfile);
 CloseFile(statfile);
 Started:=True;
end;

procedure TService1.ServiceShutdown(Sender: TService);
var statfile:Text;
begin
 AssignFile(statfile,"event.log");
 Append(statfile);
 Writeln(statfile,"ServiceShutdown(");
 Flush(statfile);
 CloseFile(statfile);
end;

end.


 
isasa ©   (2006-06-24 11:16) [20]

procedure TDS.ServiceExecute(Sender: TService);
while not Self.Terminated do
    begin
      ...
      SleepEx(5000,true);
    end;


Долго спим. Хотя умные люди пишут, что интервал ожидания ответа ~20сек.
У меня на болванке сервиса проблемы с закрютием начинаются со Sleep(3000).

Попробуй уменьшить время сна.


 
isasa ©   (2006-06-24 11:31) [21]

Отвлекли.
Или если надо выдержать именно 5000(по сну :) ), то что-то, вроде этого

<делаем что-то>
if Self.Terminated then break;
SleepEx(1000,true);
<делаем что-то>
if Self.Terminated then break;
SleepEx(1000,true);
<делаем что-то>
if Self.Terminated then break;
SleepEx(1000,true);
<делаем что-то>
if Self.Terminated then break;
SleepEx(1000,true);
<делаем что-то>
if Self.Terminated then break;
SleepEx(1000,true);

напоминает маразм, но помогает


 
Сергей М. ©   (2006-06-25 19:10) [22]

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

си. "Debugging service applications"


 
novill ©   (2006-06-27 10:11) [23]

Может понадобится кому...

Проблема остановки сервиса окончательно решена только заменой  
      SleepEx(<большое число>,True)
на цикл
      for i:=1 to CheckPeriodSec*5 do
       begin
        ServiceThread.ProcessRequests(False);
        if Self.Terminated then break;
        SleepEx(200,True);


 
isasa ©   (2006-06-27 13:10) [24]

У меня методом "научного тыка" получилось чуть больше -  SleepEx(1000,True).
200 - это слишком часто. :)


 
han_malign ©   (2006-06-27 13:40) [25]


> У меня методом "научного тыка" получилось чуть больше

- у меня, в таких случаях, существует Event (hStop: THandle)(:=CreateEvent(...)) который устанавливается в OnStop, и WaitForSingleObject - хоть INFINITE...
И "тело" обрабатывается только если (WaitForSingleObject(hStop, dwLatency) = WAIT_TIMEOUT)...


 
han_malign ©   (2006-06-27 13:44) [26]

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


 
Сергей М. ©   (2006-06-27 16:01) [27]


> по уму "рабочее тело" надо в отдельный  поток выносить


Оно и так уже в отдельном потоке работает.


> novill ©   (27.06.06 10:11) [23]


В цикле этом достаточно сделать

ServiceThread.ProcessRequests(False);
..
Sleep(0);

Но это - для "бестолкового" цикла.

"Толковый" же цикл может и должен использовать kernel time гораздо эффективней, нежели в "бестолковом" Sleep[Ex]


 
isasa ©   (2006-06-27 17:04) [28]

Я так понял, идея такая. Поток при стопе, все-таки, должен "ответить"(завершиться)(вызвать SetServiceStatus (...) ) в течении ~1-2 сек.
Прибольшем интервале - проблемы.
При простейшем потоке - Sleep(3000) дает устойчивую ошибку завершения
тело ф-ции потока

swprintf_s(locbuf, MAX_LOG_STRLEN, L"%s Still running ...", pThData->srvName);
LogMsg(IDS_MSG111); //Main Thread Enter
while (pThData->goThread==0)
{
 LogMsg(locbuf);
 ::Sleep(1000);  // По задержке уже проблемы со стопом ->  ::Sleep(3000);
}
LogMsg(IDS_MSG108); //Main Thread Exit


где

void WINAPI ServiceCtrlHandler (DWORD Opcode)
{
...
     case SERVICE_CONTROL_STOP:
  case SERVICE_CONTROL_SHUTDOWN:
   if (thData.goThread==0) {
    thData.goThread = -1;  // Нормальное завершение главного потока
    if (Opcode==SERVICE_CONTROL_STOP) {
     LogMsg(IDS_MSG109); //Stoped by system
    } else {
     LogMsg(IDS_MSG110); //SHUTDOWN by system
    }
   } else { // Ну если добрались до выполнения ветки - проблемы с логикой!
    srvStat.dwCurrentState  = SERVICE_STOPPED; //С принудительным сносом главного потока?
    srvStat.dwWin32ExitCode = 0;
    srvStat.dwCheckPoint    = 0;
    srvStat.dwWaitHint      = 0;
    LogMsg(IDS_MSG112); //Stoped by system. Call the ExitThread function for Main Thread(memory may be lost)
    if (!SetServiceStatus (srvStatHandle, &srvStat))
     LogMsg(IDS_MSG102, GetLastError());
   }
       return;
...

и, соответственно, в ф-ции сервиса

void WINAPI ServiceProc(DWORD argc, LPTSTR *argv)
{
...
   //LogMsg(IDS_MSG104); //Create Main Thread
   mhThread = CreateThread(NULL, 0, srvMainThread, &thData, 0, &mThId);
   if (mhThread!=NULL) {
     //LogMsg(IDS_MSG113);  //Main Thread Created
     WaitForSingleObject(mhThread, INFINITE);
     CloseHandle(mhThread);
     LogMsg(IDS_MSG105); //Leaving DiSpy
     srvStat.dwCurrentState  = SERVICE_STOPPED;
     srvStat.dwWin32ExitCode = 0;
     srvStat.dwCheckPoint    = 0;
     srvStat.dwWaitHint      = 0;
     if (!SetServiceStatus (srvStatHandle, &srvStat))
       LogMsg(IDS_MSG102, GetLastError());
     } else
       LogMsg(IDS_MSG107); //Error Create Main Thread
   return;


 
novill ©   (2006-07-11 11:52) [29]


> Сергей М.


> Но это - для "бестолкового" цикла.
>
> "Толковый" же цикл может и должен использовать kernel time
> гораздо эффективней, нежели в "бестолковом" Sleep[Ex]

Как сделать "толковый" цикл?
Если мне тело сервиса надо выполнять раз в минуту или реже


 
tesseract ©   (2006-07-11 11:58) [30]

> Как сделать "толковый" цикл?
> Если мне тело сервиса надо выполнять раз в минуту или реже

Делается два потока, один основной который ожидает сообщения - на исполнение или завершение, и второй, который по таймеру эти сообщения посылает основному.

Вроде на пальцах просто :-)


 
Сергей М. ©   (2006-07-11 12:01) [31]


> мне тело сервиса надо выполнять раз в минуту или реже


Значит нужно организовать таймер и обрабатывать сообщение WM_TIMER


 
Nickla   (2006-10-11 15:27) [32]

У меня другая проблема


procedure TWebShotService.ServiceExecute(Sender: TService);
begin
 while not Terminated do
 begin
   CameraEngine.WorkCamera;
   ServiceThread.ProcessRequests(False);
   Sleep(10);
 end;
end;


Так вот все равно ошибка вылазиет при останове. Добавил Stoped := true все равно вылазиет.

CameraEngine.WorkCamera; работает максимум 1-10мс. То есть большой задержки нет. Но ошибка периодически вылазиет.

Гдето видел альтернативный способ создания приложения. Просто ощущение что это баг ДНК TServise


 
Nickla   (2006-10-11 15:36) [33]

Нашел интереснейшую ссылку

http://www.achatfs.narod.ru/create_services_api.html


 
Сергей М. ©   (2006-10-11 15:43) [34]


> Nickla   (11.10.06 15:27) [32]


Делфи-отладчик писан борландом не для Пушкина


 
Nickla   (2006-10-13 10:01) [35]

Удалено модератором
Примечание: Создание пустых сообщений



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

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

Наверх




Память: 0.55 MB
Время: 0.037 c
2-1171019204
kot_michael
2007-02-09 14:06
2007.02.25
Добавление пользователей в AD


1-1168240005
DelphiLexx
2007-01-08 10:06
2007.02.25
DBGrid (DBGridEh) и dgColLines


11-1148312816
Vladimir Kladov
2006-05-22 19:46
2007.02.25
Версия 2.36


3-1165217802
Kolan
2006-12-04 10:36
2007.02.25
Неполучается настоить MSSql.


2-1170756864
Cara
2007-02-06 13:14
2007.02.25
ADOConnection и Acceess





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