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

Поиск:

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


Шустрый
*


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

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



Приветствую!
Сделал Службу для WinXP. Что происходит - В службе работает таймер и через определенные промежутки времени проверяет определённые данные, если всё ок - запускается exe-шник (через CreateProcess), выполяет свою работу и гасится, если условиям не соответствует - ничего и не запускается. Всё работает нормально, без проблем.
Возникла потребность проделать аналогичную штуку с другим exe файлом, т.е. так же через определённые промежутки времени проверять свои условия и если ок - запускать файл, а нет - так нет.
Т.к. обе операции относятся к одной теме - делать вторую службу не очень хочется. Решил реализовать всё в одной - разместил второй таймер, по которому выполяются аналогичные действия со вторым exe файлом.
Все в принципе тоже работает, но есть проблема! Если исполнение первого exe проходит достаточно быстро, что не нужно парится о "успел/не успел выполнить", то со вторым файлом время может растянуться.
Сделал так:
Код

         OStartEn := CreateProcess(nil,
         CmdStr,
         nil, 
         nil,
         False, 
         CREATE_NEW_CONSOLE or 
         NORMAL_PRIORITY_CLASS,
         nil, 
         nil,
         OStartupInfo, 
         OProcessInfo);
         if OStartEn then
          begin
           WaitForSingleObject(OProcessInfo.hProcess, INFINITE);
           CloseHandle(OProcessInfo.hThread);
           CloseHandle(OProcessInfo.hProcess);
           OStartEn := False;
          end;

Все работает, но из-за WaitForSingleObject, срабатывающей во втором таймере, события первого таймера выполняются только после окончания её работы.
Подскажите, как сделать так, что бы каждый таймер жил своей жизнью, вне зависимости от того, что происходит в другом?
PM MAIL   Вверх
MetalFan
Дата 15.3.2011, 19:32 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

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



Лучший вариант: Отказаться от таймеров. Использовать потоки.
Худший:
Вместо WaitForSingleObject(OProcessInfo.hProcess, INFINITE)
написать нечто подобное:
Код

  while WaitForSingleObject(OProcessInfo.hProcess, 500) = WAIT_TIMEOUT do
     Application.ProcessMessages;

вместо Application.ProcessMessages  возможно понадобится цикл из PeekMessage-DispatchMessage

Это сообщение отредактировал(а) MetalFan - 15.3.2011, 19:33


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Litta
Дата 15.3.2011, 19:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Вот как раз нашел вариант про
Код

while WaitForSingleObject(OProcessInfo.hProcess, 500) = WAIT_TIMEOUT do


Только именно Application.ProcessMessages не проходит в службе!
Можно по-подробней о предлагаемом Вами цикле? Я просто со службами и вобще в системном программинге не очень специализируюсь  smile 
PM MAIL   Вверх
MetalFan
Дата 15.3.2011, 22:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

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



Ну как-то так наверное:
Код

  while PeekMessage(AMsg, 0, 0, 0, PM_REMOVE ) <> 0 do
    DispatchMessage(AMsg);


А вообще лучше отказаться от TTimer'а в службе (о нем ведь речь?).


Это сообщение отредактировал(а) MetalFan - 15.3.2011, 22:18


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Litta
Дата 16.3.2011, 11:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Да, речь о нём.
Попробовал следующее:
Код

OStartEn := CreateProcess(nil,
CmdStr,
nil,
nil,
False,
CREATE_NEW_CONSOLE or
NORMAL_PRIORITY_CLASS,
nil,
nil,
OStartupInfo,
OProcessInfo);
if OStartEn then
 begin
   while PeekMessage(AMsg, 0, 0, 0, PM_REMOVE) do
     begin
       if AMsg.Message = wm_Quit then Halt(AMsg.WParam);
       TranslateMessage(AMsg);
       DispatchMessage(AMsg);
      end;
     TerminateProcess(OProcessInfo.hProcess, 0);
     CloseHandle(OProcessInfo.hThread);
     CloseHandle(OProcessInfo.hProcess);
     OStartEn := False;
    end;

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

Это сообщение отредактировал(а) Litta - 16.3.2011, 12:17
PM MAIL   Вверх
MetalFan
Дата 16.3.2011, 12:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

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



Цитата(Litta @  16.3.2011,  11:59 Найти цитируемый пост)
Попробовал следующее:

а где WaitForSingleObject???


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Litta
Дата 16.3.2011, 13:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Пардон, ступил  smile 
Написал так:
Код

OStartEn := CreateProcess(nil,
CmdStr,
nil,
nil,
False,
CREATE_NEW_CONSOLE or
NORMAL_PRIORITY_CLASS,
nil,
nil,
OStartupInfo, 
OProcessInfo);
if OStartEn then
 begin
   while (WaitForSingleObject(OProcessInfo.hProcess, 100)<>WAIT_OBJECT_0) do
     begin
       while PeekMessage(AMsg, 0, 0, 0, PM_REMOVE) do
         begin
           if AMsg.Message = wm_Quit then Halt(AMsg.WParam);
           TranslateMessage(AMsg);
           DispatchMessage(AMsg);
         end;
     end;
   TerminateProcess(OProcessInfo.hProcess, 0);
   CloseHandle(OProcessInfo.hThread);
   CloseHandle(OProcessInfo.hProcess);
   OStartEn := False;
 end;

Вроде работает, оба файла запускаются когда нужно и отрабатывают что нужно!
Ничего не забыл или может что лишнее в коде?
Спасибо большое за помощь!

ЗЫ: а как такую задачу решить с помощью потоков? Мне нужно через определённые промежутки времени проверять параметры и если ок - запускать файлы (что б не висели в памяти лишним грузом, а запускались лишь тогда, когда это нужно). Соответственно проверку параметров запускаю в таймерах через определенные промежутки времени, ну и в таймере уже создаю процесс если параметры соответствующие. А какая логика должна быть в использовании в службе вместо таймеров - потоков (в них я тож просто не особо шарю, отсюда и вопрос, было бы интересно разобраться)?
PM MAIL   Вверх
MetalFan
Дата 16.3.2011, 14:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

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



Цитата(Litta @  16.3.2011,  13:13 Найти цитируемый пост)
<>WAIT_OBJECT_0

не рекомендую так писать... так как в общем случае цикл будет вечен в случае ошибки.
Я ранее писал, что надо проверять на соответствие WAIT_TIMEOUT, в случае завершения ожидания или ошибки - выход из цикла.
Цитата(Litta @  16.3.2011,  13:13 Найти цитируемый пост)
if AMsg.Message = wm_Quit then Halt(AMsg.WParam);

Не уверен, что эта строчка имеет смысл в службе, да и Halt делать совсем жестоко.
в TranslateMessage в данном случае нет необходимости.
TerminateProcess - зачем???

По поводу потоков - здесь на форуме есть отличная статья по ним в разделе WinApi.
В твоем случае можно было бы вообще обойтись без потоков и таймеров.
Просто в цикле отмерять нужный промежуток времени с пом.GetTickCount.


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Litta
Дата 16.3.2011, 14:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата

Я ранее писал, что надо проверять на соответствие WAIT_TIMEOUT, в случае завершения ожидания или ошибки - выход из цикла.


Но я так понимаю, что в этом случае я должен знать приблизительно сколько времени требуется для правильной работы проги и выставлять соответствующее WaitForSingleObject(OProcessInfo.hProcess, 5000) ?
Но время работы будет варьироваться и надежней с точки зрения не повреждения данных (а прога пишет данные в таблицы) дать ей завершится самой (естесственно внутри расставлены все Try except, а в конце работы вобще Application.Terminate), или я не правильно понял значение WAIT_TIMEOUT?
PM MAIL   Вверх
MetalFan
Дата 16.3.2011, 16:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

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



Litta, зачем нужно знать, сколько времени надо для работы??? просто поменять условие продолжения цикла с <> WAIT_OBJECT_0 на = WAIT_TIMEOUT.



--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Litta
Дата 16.3.2011, 17:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Именно про это я и написал - что не правильно понял про WAIT_TIMEOUT  smile 
Изменил, ещё раз большое спасибо!
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.1974 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


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

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