Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Служба 
V
    Опции темы
m1nder
Дата 27.9.2009, 20:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 23.9.2009
Где: Нижний Новгород

Репутация: нет
Всего: нет



Здравствуйте! Подскажите как мне корректно завершить службу. Допустим есть простенький код:

Код


procedure Ttask5.ServiceExecute(Sender: TService);
begin
  sleep(10000);
  MoveFile('c:\test.pdf','d:\test.pdf');
  task3.DoPause;
While not Terminated do
ServiceThread.ProcessRequests(True);
  end;

procedure Ttask5.ServicePause(Sender: TService; var Paused: Boolean);
begin
task5.DoStart;
end;



Если вручную завершать службу, то она вылетает с ошибкой, я понимаю, что нужно обработать остановку, но вот только как?
Заранее благодарю!
PM MAIL WWW ICQ   Вверх
Virtuals
Дата 28.9.2009, 06:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 476
Регистрация: 27.11.2006

Репутация: 4
Всего: 11



m1nder, ничего непонятно, показывай код полностью!.
а так

Код

procedure Ttask5.ServicePause(Sender: TService; var Paused: Boolean);
begin
if смогли_паузу then Paused:=true else Paused:=false;
end;

procedure TService1.ServiceShutdown(Sender: TService);
begin
 остановить всю работу.
end;



PM MAIL ICQ   Вверх
m1nder
Дата 28.9.2009, 11:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 23.9.2009
Где: Нижний Новгород

Репутация: нет
Всего: нет



Программа сравнивает файлы по датам каждые 10 сек и если они разные - переписывает. Проблемка с остановкой службы. Как корректно остановить службу и завершить ее?

Код

procedure Ttask9.ServiceExecute(Sender: TService);
var file1 : string;
    file2 : string;
    intFileAge1: integer;
    intFileAge2: integer;

begin
  sleep(10000); // 10 сек

  file1:=ParamStr(1);
  file2:=ParamStr(2);

  intFileAge1 := sysutils.FileAge(file1);
  intFileAge2 := sysutils.FileAge(file2);
if intFileAge1 <> intFileAge2 then
  CopyFile(PChar(file1),PChar(file2), false);
  task9.DoPause;
While not Terminated do
ServiceThread.ProcessRequests(True);
  end;

procedure Ttask9.ServicePause(Sender: TService; var Paused: Boolean);
begin
task9.DoStart;
end;

procedure Ttask9.ServiceShutdown(Sender: TService);
begin
  task9.DoStop;
end;


Модератор: не забываем использовать кнопку КОД





Это сообщение отредактировал(а) bems - 28.9.2009, 12:24
PM MAIL WWW ICQ   Вверх
CodeMonkey
Дата 28.9.2009, 11:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 16
Всего: 89



Что ЭТО?

Код
procedure Ttask9.ServicePause(Sender: TService; var Paused: Boolean);
begin
  task9.DoStart;
end;

procedure Ttask9.ServiceShutdown(Sender: TService);
begin
  task9.DoStop;
end;



--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Virtuals
Дата 28.9.2009, 13:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 476
Регистрация: 27.11.2006

Репутация: 4
Всего: 11



CodeMonkey, это его сервис сам себя в "прошлое" отправляет smile.

m1nder
ты блин зачем основной поток сервиса вообще трогаеш?.
в ServiceExecute ты должен инициализировать все что нужно, и выполнять свое грязное дело внутри цикла
Код

While not Terminated do
ServiceThread.ProcessRequests(True);
  end;

а то что у тебя отрабатывает 1 раз и все.
в идеале, ServiceExecute вообще не трогают а отрабатывают по сообщениям

Код

ServiceStart(Sender: TService; var Started: Boolean);
ServiceStop(Sender: TService; var Stopped: Boolean);
ServiceShutdown(Sender: TService);
ServicePause(Sender: TService; var Paused: Boolean);


тоесть в отдельном потоке.

ЗЫ имхо сделай для начала свою процедуру отдельным потоком (и отлаживать легче будет)
типа 
Код

type
  TThreadcheckfiledate=class(TThread)
  protected
    procedure Execute; override;
  end;
var
  TCD: TThreadcheckfiledate;
...

а потом уже в сервисы лезь.
PM MAIL ICQ   Вверх
m1nder
Дата 30.9.2009, 17:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 23.9.2009
Где: Нижний Новгород

Репутация: нет
Всего: нет



Пробовал по всякому, не получается нормальной работы со службой. Virtuals, подскажи как  правильно 
Код

While not Terminated do
ServiceThread.ProcessRequests(True);
  end;

в цикл сунуть или как это при помощи потоков сделать. Подскажите поподробнее, пожалуйста.
PM MAIL WWW ICQ   Вверх
CodeMonkey
Дата 30.9.2009, 20:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 16
Всего: 89





--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Keeper89
Дата 30.9.2009, 23:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2580
Регистрация: 26.2.2009

Репутация: 14
Всего: 58



У CodeMonkey на все случаи жизни статьи есть smile 


--------------------
PM MAIL WWW   Вверх
m1nder
Дата 1.10.2009, 15:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 23.9.2009
Где: Нижний Новгород

Репутация: нет
Всего: нет



Пробую через поток, но ничего не выходит! В чем причина?

Код


// Объявляем мой поток
  TNewThread = class(TThread)
    private
    { Private declarations }
  protected
    procedure Execute; override;
  end;

var
  Service3: TService3;
  NewThread: TNewThread;
implementation

{$R *.DFM}

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

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

// Выполняется мой поток

procedure TNewThread.Execute;
 var file1, file2: string;
begin
 While not Terminated do
  begin
{
 ----  Тест ----------------
  sleep(5000); // 5 сек
  file1:='c:\test\test.txt';
  file2:='d:\test\test.txt';
  CopyFile(PChar(file1),PChar(file2), false);
 }

  end;
 end;

// Запускаем мой поток из главного
procedure TService3.ServiceExecute(Sender: TService);
var
  NewThread: TNewThread;
begin
  NewThread:=TNewThread.Create(true);
  NewThread.FreeOnTerminate:=true;
  NewThread.Priority:=tpLower;
  NewThread.Resume;
end;



А через OnStart и OnStop у меня не получается. Пробовал по всякому, иногда запускаешь службу - процесс выполняется, а служба не стартует и выснет. А через Execute цикл While not Terminated do отрабатывает 1 раз. Напишите мне пару строк как сделать и забыть, там же много кода не нужно, заодно я разберусь.
PM MAIL WWW ICQ   Вверх
CodeMonkey
Дата 1.10.2009, 17:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 16
Всего: 89



Эх, ещё один шедевр.

Что, по-вашему, должна делать служба, если её Execute-тело заканчивается? 

Цитата(m1nder @  1.10.2009,  15:42 Найти цитируемый пост)
заодно я разберусь. 

Да ни черта вы не разберётесь вы, а втупую запомните пример. 
Учитесь мыслить и делать выводы самостоятельно. Вам это ничто не заменит.

Пример несложного мозгового упражнения. Написано: 

Цитата
Вы можете реализовать работу службы двумя способами.

Вариант первый: стартует служба, вы начинаете что-то делать, время от времени уведомляя систему о своём состоянии, потом служба останавливается.

Вариант второй: стартует служба, создаёт рабочие потоки. По уведомлению от системы потоки останавливаются и служба выключается.

Итак, событие OnExecute реализует первый вариант: вы просто вписываете весь код службы в OnExecute, ....

Для второго варианта реализации вы не должны назначать обработчик OnExecute, но обязаны реализовать, как минимум, OnStart и OnStop. В первом обработчике вы запускаете рабочие потоки службы, а в OnStop — останавливаете. ...


Внимание, наводящий вопрос: нафига вы назначили OnExecute, если в нём вы создаёте поток?

Право же, это несложно.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
m1nder
Дата 1.10.2009, 18:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 23.9.2009
Где: Нижний Новгород

Репутация: нет
Всего: нет



Всем огромное спасибо!!! Особенно Вам, CodeMonkey! Написал наконец свою программу +) оказалось все просто. Выложу код, вдруг кому понадобится:
Код


{Программа-служба, сравнивает файлы в двух каталогах каждые N минут и если они разные по дате - перезаписывает} 
...
procedure TService2.ServiceExecute(Sender: TService);
var  F: TSearchRec;
     Path, source,files: string;
     Attr,intFileAge1,intFileAge2: Integer;

begin

  path:='d:\test\';   //ParamStr(1)
  source:='i:\test\'; //ParamStr(2)
  files:='';
  Attr:= faAnyFile;
  intFileAge1:=0;
  intFileAge2:=0;

 while not terminated  do
  begin

//-------------------------------------
    sleep(5000); // 5 сек
    FindFirst(Path+'*.*', Attr, F);
    if F.name <> '' then files:= F.Name;
      if intFileAge1 <> intFileAge2 then
        CopyFile(PChar(path + files),PChar(source+files),false);
    while (FindNext(F) = 0) do
      begin
        files:=F.Name;
        intFileAge1 := sysutils.FileAge(path + files);
        intFileAge2 := sysutils.FileAge(source+files);
        if intFileAge1 <> intFileAge2 then
        CopyFile(PChar(path + files),PChar(source+files),false);
      end;
    FindClose(F);
//-------------------------------------
    Service2.ReportStatus;
    if Service2.Status=csStopped then DoStop;
    if Service2.Status=csPaused then DoPause;

  end;

end;


PM MAIL WWW ICQ   Вверх
Virtuals
Дата 6.10.2009, 05:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 476
Регистрация: 27.11.2006

Репутация: 4
Всего: 11



m1nder, ну нафига sleep(5000); // 5 сек внутри цикла?
статью внимательней читай.
Цитата

ReportStatus — если вы делаете что-либо слишком долго (дольше, чем число миллисекунд, указанных в свойстве WaitHint), то вы должны вызывать этот метод для сообщения системе, что вы ещё живы. Если вы будете выполнять какие-то действия в обработчиках событий или коде инициализации/завершения слишком долго, то SCM может подумать, что ваша служба зависла, и, в некоторых случаях, завершить её (но чаще всего SCM просто вернёт ошибку приложению, запросившему действие).


Цитата

WaitHint (свойство) — указывает время в миллисекундах, через которое ваша служба должна сообщить свой статус. VCL по умолчанию ставит это свойство в 5000 (т.е. 5 секунд), хотя в системе по умолчанию этот параметр принимается равным 2000. Как разработчик службы, вы должны определить, как часто служба должна сообщать о своём статусе. Вы также должны вызывать ReportStatus не реже, чем вы указали в WaitHint. Если вы собираетесь выполнить какие-то длительные действия в обработчике события, то иногда проще вынести эти действия в отдельный поток, а в обработчике события сделать цикл ожидания завершения работы с периодическим вызовом ReportStatus раз в, скажем, WaitHint / 2 миллисекунд. Разумеется, цикл не должен крутиться вхолостую, а ждать наступления момента вызова ReportStatus или завершения работы.

PM MAIL ICQ   Вверх
papweilm
Дата 29.11.2022, 06:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 28.11.2022

Репутация: нет
Всего: нет




Модератор: Сообщение скрыто.

PM MAIL   Вверх
saiple
Дата 24.12.2022, 13:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 22.11.2022

Репутация: нет
Всего: нет



levitra 10 mg reviews <a href=" https://levitraoffer.com/# ">what is vardenafil 20mg</a> buy generic levitra online
PM MAIL   Вверх
saiple
Дата 28.12.2022, 18:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 22.11.2022

Репутация: нет
Всего: нет



what is levitra used for <a href=" https://levitraoffer.com/# ">levitra pills men</a> levitra 20 mg film coated tablets
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • 99% ответов по WinAPI можно найти в MSDN Library, оставшиеся 1% здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.1636 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.