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

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

Написание службы с циклом


Страницы:   1 2

Molnia ©   (2010-08-11 09:08:00) 

Доброго времени суток уважаемые знатоки. Необходимо написать сервис VCL, который по таймеру будет выполнять определенные действия. Код который нужно выполнять есть, но проблема в том что сервис не запускает таймер =( Google не выдал ни одного рабочего примера. Пожалуйста дайте исходник работающего сервиса который например по таймеру пишет в файл фразу.

Заранее благодарю.


FillAll   (2010-10-11 17:17:00) [1]

sniknik - Спасибо. Объяснил доходчиво. Я заглядывал но не понял.


sniknik   (2010-10-11 16:48:00) [2]

чего там объяснять, исходники генофонда пропали что ли?
смотришь в них -
procedure TServiceThread.Execute;
var
 msg: TMsg;
 Started: Boolean;
begin
 PeekMessage(msg, 0, WM_USER, WM_USER, PM_NOREMOVE); { Create message queue }
 try
   FService.Status := csStartPending;
   Started := True;
   if Assigned(FService.OnStart) then FService.OnStart(FService, Started);
   if not Started then Exit;
   try
     FService.Status := csRunning;
      if Assigned(FService.OnExecute) then
       FService.OnExecute(FService)

     else
        ProcessRequests(True);
     ProcessRequests(False);
   except
     on E: Exception do
       FService.LogMessage(Format(SServiceFailed,[SExecute, E.Message]));
   end;
 except
   on E: Exception do
     FService.LogMessage(Format(SServiceFailed,[SStart, E.Message]));
 end;
end;

все очевидно.


FillAll   (2010-10-11 16:33:00) [3]

У меня есть подозрение что в компоненте TService есть внутренний Thread, который и поддерживает такой невизуальный VCL компонент как TTimer.
Это просто любопытство. Я попробовал (текст приводить не буду) запустить сервис с обработкой парадоксовских таблиц используя TTable к стандартному BDDEMOS псевдониму (простите за терминологию Paradox 5).
Пробовал "бросить" на Service1 невизуальные компоненты TserverSocket, TWordApplication - сервис активен если есть эти компоненты и выполнена процедура Create.
Я еще попробовал объявить в тексте (а не "бросить") такие компоненты и создать командой
Create(self) - сервис работает
и командой
Create(Nil) - сервис не работает (спустя некоторое время останавливается)
Наверное я был прав - есть внетренний Thread.

Может кто объяснит?


Palladin   (2010-10-10 01:05:00) [4]


> Посчитал - интервал - 16 минут 39 секунд. Примерно совпадает.

что значит примерно? совпадает полностью, в точности до секунды
считать научись


FillAll   (2010-10-09 21:55:00) [5]

Попробовал.
Докладаю.
Поставил свойство Interval равным 999000.
Запустил.
Через некоторое время читаю в файле:
09.10.2010 20:24:53 событие таймера.
09.10.2010 20:41:32 событие таймера.
Посчитал - интервал - 16 минут 39 секунд. Примерно совпадает.

Вспомнил анекдот: Это не возможно объяснить. Это надо запомнить.


FillAll   (2010-10-09 20:58:00) [6]

Сергей М.
А возьми и попробуй.
Я когда прочитал комментарий
А у тебя мало того что ProcessRequests() нигде не вызывается, так еще и обработчика OnExecute нет в принципе. При отсутствии этого обработчика сервис останавливается тут же сразу после старта, ибо ему попросту делать нечего - обработчика-то нет)
Запустил сервис, перегрузил компьютер, десять минут жду - полет нормальный.
Правда задумался:интервал 1 секунда, если 10 минут?
попробую - доложу.


Dennis I. Komarov   (2010-10-04 17:15:00) [7]

1. Выбросить таймер ...... (вобщем, далеко очень)
2. Доп. поток для разного рода действий, основной оставить в покое.


Сергей М.   (2010-10-03 22:38:00) [8]


> если надо - приостанавливается и продолжить можно. Все как
> по нотам


Ну эт ты врешь)

Сервис реагирует на команды (в т.ч. на pause и resume) именно потому что в OnExecute в цикле вызывается ProcessRequests().
А у тебя мало того что ProcessRequests() нигде не вызывается, так еще и обработчика OnExecute нет в принципе. При отсутствии этого обработчика сервис останавливается тут же сразу после старта, ибо ему попросту делать нечего - обработчика-то нет)


FillAll   (2010-10-03 22:08:00) [9]

Я тут попробовал в семерочке. Создал ServiceApplication.На service1 кинул Timer1 и написал код:



unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs,
 ExtCtrls, Registry;

const
 cRegPath    = '\SYSTEM\CurrentControlSet\Services\';
 cImagePath  = 'ImagePath';

type
 TService1 = class(TService)
   Timer1: TTimer;
   procedure ServiceStart(Sender: TService; var Started: Boolean);
   procedure ServicePause(Sender: TService; var Paused: Boolean);
   procedure ServiceContinue(Sender: TService; var Continued: Boolean);
   procedure ServiceStop(Sender: TService; var Stopped: Boolean);
   procedure Timer1Timer(Sender: TObject);
 private
   { Private declarations }
   ServicePath: String;
 public

   function GetServiceController: TServiceController; override;
   { Public declarations }
 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.ServiceStart(Sender: TService; var Started: Boolean);
var
 Reg: TRegistry;
 vImagePath: String;
begin
 //start
 // оределяем путь к папке сервиса
 Reg := TRegINIFile.Create('');
 Reg.RootKey := HKEY_LOCAL_MACHINE;
 Reg.OpenKey(cRegPath+Name, True);
 vImagePath:=Reg.ReadString(cImagePath);
 ServicePath:=ExtractFilePath(vImagePath);
 Reg.Free;
 // запускаем таймер
 Timer1.Enabled:=True;
end;

procedure TService1.ServicePause(Sender: TService; var Paused: Boolean);
begin
 // pause
 Timer1.Enabled:=False;
end;

procedure TService1.ServiceContinue(Sender: TService;
 var Continued: Boolean);
begin
 // continue
 Timer1.Enabled:=True;
end;

procedure TService1.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
 // stop
 Timer1.Enabled:=False;
end;

procedure TService1.Timer1Timer(Sender: TObject);
var
 f: TextFile;
begin
 // on timer
 {$I-}
 AssignFile(f,ServicePath+'Log.log');
 Append(f);
 if IOResult <> 0 then
   Rewrite(f);
 Writeln(f,DateTimeToStr(Now)+' событие таймера.');
 CloseFile(f);
 {$I+}
end;

end.


и все работает. Может вы зря на ServiceExecute надеялись?


FillAll   (2010-10-03 22:03:00) [10]

Хотел понять в чем проблема - не понял.
Я тут в семерочке создал ServiceApplication, кинул на него таймер инаписал вот такую фигню:

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs,
 ExtCtrls, Registry;

const
 cRegPath    = '\SYSTEM\CurrentControlSet\Services\';
 cImagePath  = 'ImagePath';

type
 TService1 = class(TService)
   Timer1: TTimer;
   procedure ServiceStart(Sender: TService; var Started: Boolean);
   procedure ServicePause(Sender: TService; var Paused: Boolean);
   procedure ServiceContinue(Sender: TService; var Continued: Boolean);
   procedure ServiceStop(Sender: TService; var Stopped: Boolean);
   procedure Timer1Timer(Sender: TObject);
 private
   { Private declarations }
   ServicePath: String;
 public

   function GetServiceController: TServiceController; override;
   { Public declarations }
 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.ServiceStart(Sender: TService; var Started: Boolean);
var
 Reg: TRegistry;
 vImagePath: String;
begin
 //start
 // оределяем путь к папке сервиса
 Reg := TRegINIFile.Create('');
 Reg.RootKey := HKEY_LOCAL_MACHINE;
 Reg.OpenKey(cRegPath+Name, True);
 vImagePath:=Reg.ReadString(cImagePath);
 ServicePath:=ExtractFilePath(vImagePath);
 Reg.Free;
 // запускаем таймер
 Timer1.Enabled:=True;
end;

procedure TService1.ServicePause(Sender: TService; var Paused: Boolean);
begin
 // pause
 Timer1.Enabled:=False;
end;

procedure TService1.ServiceContinue(Sender: TService;
 var Continued: Boolean);
begin
 // continue
 Timer1.Enabled:=True;
end;

procedure TService1.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
 // stop
 Timer1.Enabled:=False;
end;

procedure TService1.Timer1Timer(Sender: TObject);
var
 f: TextFile;
begin
 // on timer
 {$I-}
 AssignFile(f,ServicePath+'Log.log');
 Append(f);
 if IOResult <> 0 then
   Rewrite(f);
 Writeln(f,DateTimeToStr(Now)+' событие таймера.');
 CloseFile(f);
 {$I+}
end;

end.

Самое удивительное - с интервалом в одну секунду пишет в Log.log как миленький. А если надо - приостанавливается и продолжить можно. Все как по нотам. Может вы, ребята зря с Execute методом связались?


Anatoly Podgoretsky   (2010-08-11 21:30:00) [11]

> Сергей М.  (11.08.2010 13:45:22)  [22]

FileMode для текстовых файлов не применим.
И
> FileMode is declared as a variable, not as a threadvar. Therefore this
> variable is not thread-safe.


Anatoly Podgoretsky   (2010-08-11 21:28:00) [12]

> Molnia  (11.08.2010 11:41:16)  [16]

Код не видим.


Anatoly Podgoretsky   (2010-08-11 21:27:00) [13]

> Molnia  (11.08.2010 11:19:11)  [11]

Текстовый файл, открытый для чтения, а ты пытаешься записать туда, вот тебе
и исключение.


Сергей М.   (2010-08-11 13:45:00) [14]


> Molnia ©   (11.08.10 12:23) [20]
> Reset открывает файл для чтения, а не записи


Сам придумал ?)

Читаем справку:

Reset opens the existing external file with the name assigned to F using the mode specified by the global FileMode variable

Там же в справке рядом, кстати, и примерчик имеется)


George   (2010-08-11 13:25:00) [15]


> Molnia ©   (11.08.10 12:23) [20]

Ой ли?


Molnia   (2010-08-11 12:23:00) [16]


> файл недоступен для записи или что-то вроде того?

Reset открывает файл для чтения, а не записи. Вся проблема была только в этом, через потоки тоже попробовал, замечательно работает, через таймер тоже.


George   (2010-08-11 12:16:00) [17]


> Molnia ©   (11.08.10 11:44) [18]

файл недоступен для записи или что-то вроде того?


Molnia   (2010-08-11 11:44:00) [18]


> PS. Справку по Reset уже прочитал?

Блиииин так и знал что ошибка будет идиотская. Огромное спасибо.


Плохиш   (2010-08-11 11:42:00) [19]


> Molnia ©   (11.08.10 09:08)  


> но проблема в том что сервис не запускает таймер

Сервисы ничего не запускают, для запусков существуют программисты. Вам стоит одного из них поискать.


Molnia   (2010-08-11 11:41:00) [20]


> Ну опять же - с чего ты взял что "ни разу" ?
> То что в файл не добавляется строка 'test', запросто может
> говорить о падении сервиса на строчке Reset()
>
>

Добавил Try/except, сейчас служба работает, не останавливается, но ничего в файл не пишет.


Страницы:   1 2

Наверх

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