Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 01.04.2012, 22:07   #1
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,442
По умолчанию [Delphi] Правильно организовать работу сервиса

Доброго времени суток!

Ситация следующая:
Написал сервис на основе TService.

Сервис вырубается отработав действие.


WaitHint выставил на 5000 мс.
Стоит таймер, написанный на основе мультимедийных таймеров системы, котрый в период WaitHint/2 отправляет свой статус SCM.

По событию Start я инициализирую базовый класс, который не сразу, но пускает рабочие потоки(там тоже стоят мм-таймеры).
По событию Stop,Shutdown вся эта шабулда прикрывается.


Проблема:
Сервис вырубается.
Как удержать его в рабочем состоянии?

Вот осн. модуль:
Код:
unit MainSrvcUnit;

interface

uses
  Winapi.Windows,
  Vcl.SvcMgr,
  uSettingsUnit,

  clMMTimerClass,
  System.SysUtils,
  System.Classes;

type
  TSysInfo = class(TService)
    procedure ServiceBeforeInstall(Sender: TService);
    procedure ServiceStart(Sender: TService; var Started: Boolean);
    procedure ServiceStop(Sender: TService; var Stopped: Boolean);
    procedure ServiceCreate(Sender: TObject);
    procedure ServiceDestroy(Sender: TObject);
    procedure ServiceShutdown(Sender: TService);
  private
    { Private declarations }
    fTimer: TMMTimer;
    procedure OnfTimer(Sender: TObject);
  public
    function GetServiceController: TServiceController; override;
    { Public declarations }
  end;

var
  SysInfo: TSysInfo;

implementation

uses
  uConstsVars,
  clLogFileClass;

{$R *.DFM}

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

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

procedure TSysInfo.OnfTimer(Sender: TObject);
begin
  ReportStatus;
end;

procedure TSysInfo.ServiceBeforeInstall(Sender: TService);
begin
  // Загружаем имя сервиса =)
  SysInfo.DisplayName := Settings_GetServiceName;
  Log('ServiceBeforeInstall = ' + SysInfo.DisplayName);
end;

procedure TSysInfo.ServiceCreate(Sender: TObject);
begin
  Log('_ServiceAction>Create...');
end;

procedure TSysInfo.ServiceDestroy(Sender: TObject);
begin
  Log('_ServiceAction>Destroy...');
end;

procedure TSysInfo.ServiceShutdown(Sender: TService);
begin
  Log('_ServiceAction>Shutdown...');
  if SysInfo.Status = csRunning then
    _FinalService;
end;

procedure TSysInfo.ServiceStart(Sender: TService; var Started: Boolean);
begin
  Log('_ServiceAction>Start...');
  fTimer := TMMTimer.Create;
  fTimer.Interval := 2000;
  fTimer.OnTimer := OnfTimer;
  fTimer.Enabled := True;
  _InitService;
  Started := True;
end;

procedure TSysInfo.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
  Log('_ServiceAction>Stop...');
  _FinalService;
  FreeAndNil(fTimer);
  Stopped := True;
end;

end.
Как быть.. ?

Думаю пустить поток, который будет в холостую работать, но как чтоб не грузить систему? Кроме бесконечных цикло, ничего больше в голову не лезет.
Человек_Борща вне форума Ответить с цитированием
Старый 02.04.2012, 09:50   #2
Krok27
Форумчанин
 
Аватар для Krok27
 
Регистрация: 08.07.2010
Сообщений: 505
По умолчанию

Нужно заполнить процедуру ServiceExecute.
типа
void __fastcall TLockerService::ServiceExecute(TSer vice *Sender)
{
while(!Terminated )
{

Sleep(100);
ServiceThread->ProcessRequests(false);
}
}

или delphi

procedure TService1.ServiceExecute(Sender: TService);
begin
while not Terminated do
ServiceThread.ProcessRequests(False );
end;
Знающий не говорит, говорящий не знает (С) Лао Цзы
Krok27 вне форума Ответить с цитированием
Старый 02.04.2012, 20:40   #3
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,442
По умолчанию

Нет не помогло.сервис отработывает 1 раз и отваливается. Ни ошибок.. ничего..

Как быть..
Человек_Борща вне форума Ответить с цитированием
Старый 02.04.2012, 21:09   #4
SnX
Форумчанин
 
Регистрация: 30.10.2009
Сообщений: 114
По умолчанию

Цитата:
Как удержать его в рабочем состоянии?
Вопрос с ответом. Естественно он будет вырубаться отработав требуемые действия, как и любая другая программа. -)

http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx
Что насчет Delphi и его TService, то вот первая же ссылка из гугла:
http://www.tolderlund.eu/delphi/service/service.htm

>Нет не помогло
Проверяйте еще. В классе сервиса должен быть метод, который вызывается по событию OnExecute, в нем и должен находиться основной код сервиса.
SnX вне форума Ответить с цитированием
Старый 03.04.2012, 01:10   #5
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,442
По умолчанию

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

Цитата:
Проверяйте еще. В классе сервиса должен быть метод, который вызывается по событию OnExecute, в нем и должен находиться основной код сервиса.
Ну и какой же мне код там вызывать?

Последний раз редактировалось Человек_Борща; 03.04.2012 в 01:18.
Человек_Борща вне форума Ответить с цитированием
Старый 03.04.2012, 10:17   #6
SnX
Форумчанин
 
Регистрация: 30.10.2009
Сообщений: 114
По умолчанию

Цитата:
Ну и какой же мне код там вызывать?
Откуда мне знать, не я же сервис пишу.

Выше по ссылке и в этом топике есть минимальные примеры кода, которые должны быть в OnExecute, чтобы сервис постоянно "работал".
Код:
  while not Terminated do
    begin
      ...
      Sleep(1000);
      ServiceThread.ProcessRequests(False);
    end;
SnX вне форума Ответить с цитированием
Старый 03.04.2012, 11:08   #7
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,442
По умолчанию

Цитата:
Откуда мне знать, не я же сервис пишу.
Не поспорить....
Однако нет такого кода,который можно туда внести.

у меня 2 осн. метода: _InitService, который выделает ресурсы и создает экземпляр рабочего класса и _FinalService, который останавливает рабочий экземпляр класса и освобождает ресурсы. Сама работа сервиса делается внутри класса, и её никак не вынести в OnExecute.

ещё раз почитаю ссылки, мб что-то на ум придет. А пока есть мысль создавать поток и в нем все делать, но не глупо ли это? Ведь есть же у сервиса свой осн. поток, куда и толкается OnExecute, но нужно его заставить просто работать в холостую.

Последний раз редактировалось Человек_Борща; 03.04.2012 в 11:11.
Человек_Борща вне форума Ответить с цитированием
Старый 03.04.2012, 15:01   #8
Krok27
Форумчанин
 
Аватар для Krok27
 
Регистрация: 08.07.2010
Сообщений: 505
По умолчанию

Код:
_InitService;
А что у нас в этой функции?
Там может быть ошибка по доступу и сервис просто не запускается.(прекращает работу, т.к. ему нечего делать =))) До OnExecute просто не доходит дело.
В отладчике у нас что видно?
Знающий не говорит, говорящий не знает (С) Лао Цзы

Последний раз редактировалось Krok27; 03.04.2012 в 15:04.
Krok27 вне форума Ответить с цитированием
Старый 03.04.2012, 19:10   #9
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,442
По умолчанию

Он запускается, отработывает и выключается.

При перезапуске системы, сервис сам запускается, отработывает функции и выключается.
Никаких ошибок не происходит(мониторил EurekaLog).
А мне нужно чтобы он работал постоянно.

Код:
procedure _InitService;
begin
  Log('_InitService');
  Settings_ReadConfig;
  ClientMgr := THDDManager.Create;
  ClientMgr.ScanTime := vClientCheckTimeMS;
  ClientMgr.UpdateTime := vServCheckTimeMS;
  ClientMgr.FilesUpdateTime := vClientFilesCheckTimeMS;
  ClientMgr.Enabled := True;
end;
Класс содержит в себе 3 таймера, которые выполняют опр. действия в опр. время. Таймеры мультимедийные.

Последний раз редактировалось Человек_Борща; 03.04.2012 в 19:20.
Человек_Борща вне форума Ответить с цитированием
Старый 04.04.2012, 11:30   #10
Krok27
Форумчанин
 
Аватар для Krok27
 
Регистрация: 08.07.2010
Сообщений: 505
По умолчанию

Рабочий код сервиса, который выводит раз в 5 сек MessageBox по таймеру на стол пользователя.
Код:
unit MainUnit;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.SvcMgr, Vcl.Dialogs, Vcl.ExtCtrls;

type
  TSysInfo = class(TService)
    procedure ServiceBeforeInstall(Sender: TService);
    procedure ServiceCreate(Sender: TObject);
    procedure ServiceDestroy(Sender: TObject);
    procedure ServiceExecute(Sender: TService);
    procedure ServiceShutdown(Sender: TService);
    procedure ServiceStart(Sender: TService; var Started: Boolean);
    procedure ServiceStop(Sender: TService; var Stopped: Boolean);
  private

    { Private declarations }
    fTimer: TTimer;
    procedure OnfTimer(Sender: TObject);
  public
    function GetServiceController: TServiceController; override;
    { Public declarations }
  end;

var
  SysInfo: TSysInfo;

implementation

{$R *.DFM}

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

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

procedure TSysInfo.ServiceBeforeInstall(Sender: TService);
begin
//
end;

procedure TSysInfo.ServiceCreate(Sender: TObject);
begin
//
end;

procedure TSysInfo.ServiceDestroy(Sender: TObject);
begin
//
end;

procedure TSysInfo.ServiceExecute(Sender: TService);
begin

while not Terminated do
  begin
    Sleep(100);
    ServiceThread.ProcessRequests(False );
  end;
end;

procedure TSysInfo.ServiceShutdown(Sender: TService);
begin
//
end;

procedure TSysInfo.ServiceStart(Sender: TService; var Started: Boolean);
begin
fTimer := TTimer.Create(Owner);
fTimer.Interval := 5000;
fTimer.OnTimer := OnfTimer;
fTimer.Enabled := true;
Started := true;
end;

procedure TSysInfo.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
FreeAndNil(fTimer);
end;

procedure TSysInfo.OnfTimer(Sender: TObject);

begin


  MessageBox(0,'Текст из сервиса', 'Сообщение',  MB_OK+MB_SERVICE_NOTIFICATION);
end;


end.
Ищи ошибку в старте сервиса. Попробуй последовательно подключать свои таймеры. Попробуй пошагово в отладчике пройти процедуру старта сервиса.
Знающий не говорит, говорящий не знает (С) Лао Цзы

Последний раз редактировалось Krok27; 04.04.2012 в 11:37.
Krok27 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как правильно организовать сохранение в файл delphi JK0 Помощь студентам 1 21.12.2010 21:14
Как правильно организовать непростой шаблон двоичного дерева? nowaalex Общие вопросы C/C++ 10 02.12.2010 02:47
как правильно организовать продажу своего софта? broderweb Свободное общение 11 02.12.2009 17:41
Как организовать прием и работу кладра tarakan1983 БД в Delphi 10 12.03.2009 18:30
ADO + SQL Server. Как правильно организовать одновременную работу с таблицей Mouse123 БД в Delphi 17 04.07.2008 17:35