Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

DNK
I. DNK
Баллы: 5

Подробнее »



Вопрос # 1 742

/ вопрос открыт /

Приветствую, уважаемые эксперты!Появилась следующая проблема:
некое Приложение(в form.hide) ждет пока завершится другое приложение(которое записывает в ини файл инфу о том что оно завершилось). Так вот второе приложение(как и первое) легко закрывается через ctrl+alt+del. Да и пусть но при этом первое приложение ждет отчета от второго , которое исчезло не оставив и следа. Вопрос в следующем :
Как (или может быть в каком обработчике) задать действия
при завершении программы через Ctrl+alt+del?

TeM Вопрос ожидает решения (принимаются ответы, доступен мини-форум)

Вопрос задал: TeM (статус: Посетитель)
Вопрос отправлен: 1 июля 2008, 16:55
Состояние вопроса: открыт, ответов: 3.

Ответ #1. Отвечает эксперт: Feniks

Здравствуйте, TeM!
Используйте для этого событие на форме OnCloseQuery. Оно описано в хелпе Делфи. Данное событие срабатывает, когда Windows посылает сообщение на завершение работы программы. Какое именно не помню, но кажется есть в хелпе. В этом событии есть буленовая переменная CanClose, обрабатываете, что вам надо, и даете ей соответсвующее значение. Если значение будет True, значит ваше приложение может закрываться и после этого события вступает в силу обработчик OnClose.

Желаю удачи.

Ответ отправил: Feniks (статус: Бакалавр)
Время отправки: 1 июля 2008, 17:14
Оценка за ответ: 3

Ответ #2. Отвечает эксперт: Мережников Андрей

Здравствуйте, TeM!
В обработчике OnClose или OnCloseQuery главной формы второго приложения (завершения работы, которого Вы ждете) ставите строки, записывающие инфу в ини файл, о том, что приложение завершилось. Лучше поставить в OnClose, Поскольку после OnCloseQuery необязательно происходит закрытие формы (например, если установить в OnCloseQuery CanClose в false, то выхода не произойдет и событие OnClose не наступит

Ответ отправил: Мережников Андрей (статус: Абитуриент)
Время отправки: 1 июля 2008, 17:32
Оценка за ответ: 3

Ответ #3. Отвечает эксперт: Amidamaru

Здравствуйте, TeM!
В основном это зависит от того, как первое приложение ожидает закрытие второго. Для решения данной задачи лучше использовать мьютексы (Mutex).
Второе приложение при запуске создаёт мьютекс. При проверке, первое приложение пытается открыть этот мьютекс и если его получается открыть, то второе приложение ещё открыто. Если открыть мьютекс не удаётся, то второе приложение закрыто (неважно каким способом).

Приложение:
  1.  
  2. var HMut:THandle;
  3. ...
  4.  
  5. ...
  6.  
  7. Function CheckMutex: boolean;
  8. var HMut:THandle;
  9. begin
  10.  
  11.  
  12. if HMut<>0 then
  13.  
  14. end;


Ответ отправил: Amidamaru (статус: 4-ый класс)
Время отправки: 1 июля 2008, 17:53
Оценка за ответ: 5


Мини-форум вопроса

Всего сообщений: 17; последнее сообщение — 2 июля 2008, 11:03; участников в обсуждении: 4.
TeM

TeM (статус: Посетитель), 1 июля 2008, 17:21 [#1]:

Я писал в обработчеке событий OnCloseQuery, но ничего не происходило. Т.е мне нада для начала поставить значение Лож на canclose, а потом совершать необходимые действия, после чего вернуть нужное значение?
TeM

TeM (статус: Посетитель), 1 июля 2008, 17:30 [#2]:

Диспетчер задач закрывает несмотря на значение CanClose;
TeM

TeM (статус: Посетитель), 1 июля 2008, 17:41 [#3]:

У меня такая задумка и была но сегодня я обнаружил что она не срабатывает т.к завершение через диспетчер задач не активирует ни обработчик OnClose ни OnCloseQuery ни Destroy.
Amidamaru

Amidamaru (статус: 4-ый класс), 1 июля 2008, 18:30 [#4]:

Есть ещё один способ решения этой задачи с помощью мьютексов, но описывать его здесь слишком долго. Если Вам интересно - пишите мне на e-mail. Или зайдите на канал IRC #delphiintru в сети DALNet.
Приглашаю Вас на наш IRC-канал: #delphiintru в сети DalNet.
Dron

Dron (статус: Студент), 1 июля 2008, 18:44 [#5]:

А откуда такая уверенность, что когда в диспетчере задач вы жмёте "Завершить процесс", выполняются OnCloseQuery, OnClose и пр.? А если приложение зависло? ОС просто выгрузит процесс из памяти "как есть" и никакие "ловушки" в этих событиях не сработают. Всё не так просто, как кажется. А вы тут наотвечали... Имхо, здравая идея есть только в ответе Dart Mashiro.
С уважением.
Мережников Андрей

Мережников Андрей (статус: Абитуриент), 1 июля 2008, 18:50 [#6]:

Для чего такие сложности? вот пример как надо сделать (только что проверил - работает). В событие OnCloseQuery вставляешь строки:
CanClose:=false;
свои действия по записи файла или чего-то еще
CanClose:=true;
Мережников Андрей

Мережников Андрей (статус: Абитуриент), 1 июля 2008, 18:56 [#7]:

Вопрос был про закрытие приложения через диспетчер задач. Если рассматривать возможность зависания приложения, то, действительно, лучше использовать мьютексы или семафоры. Можно еще сделать следущим образом (если второе приложение запускается из первого):

WinExec сразу после запуска приложения возвращает его дескриптор. Для определения завершения программы вы должны вызывать функцию GetModuleUsage(InstanceID), где InstanceID - дескриптор запущенного функцией WinExec приложения. Если возвращаемый результат содержит ноль, приложение завершило свою работу. Сделайте проверку в таймерном цикле и задача решена
Мережников Андрей

Мережников Андрей (статус: Абитуриент), 1 июля 2008, 18:58 [#8]:

Можно использовать FindWindow() и периодически проверять - есть ли главная форма второго приложения. Если ее нет, то второе приложение завершило работу. Вариантов масса...
Dron

Dron (статус: Студент), 1 июля 2008, 19:06 [#9]:

Вы говорите о кнопке "Снять задачу" в ДЗ, а я о кнопке "Завершить процесс". Это две разные кнопки :-) И работают они по-разному.
А вариантов действительно много. Вот вам такой ещё: можно периодически получать список процессов и искать в нём имя exe-файла той программы, которая ожидается для завершения. Нашли - программа работает, не нашли - завершила работу или была принудительно завершена.
С уважением.
TeM

TeM (статус: Посетитель), 1 июля 2008, 20:28 [#10]:

Да, в hide форма(все приложение если она единственная) видно только в процессах и завершить задачу просто не найдет его,- завершить процесс об этом шла речь.

Я написал сюда в надежде на то что я незнаю какого нибудь элементарного действия для борьбы с этим "недугом". Переделывать сам вариант проверки ,я думаю, уже поздно.
Есть ли способ ценою 5-6 командных строк, создать реакцию при нажатии кнопки [Завершить процесс] в ДЗ дописывающую в ини одын символ?
Dart Mashiro Длинно обьяснять принцип работы или саму структуру?
Мережников Андрей

Мережников Андрей (статус: Абитуриент), 1 июля 2008, 20:52 [#11]:

Замечание по поводу использования мьютекса - при завершении работы процесса мьютекс автоматически не освобождается. Для этого необходимо в потоке, занявшем мьютекс выполнить CloseHandle().
Amidamaru

Amidamaru (статус: 4-ый класс), 1 июля 2008, 20:56 [#12]:

В смысле командных строк, не меняя кода 2й формы? И чем тебе не подходит мой первый способ?
Длинно и принцип работы и саму структуру. Но если ты знаешь как работают мьютексы и WaitForSingleObject, то я могу просто написать код.
Приглашаю Вас на наш IRC-канал: #delphiintru в сети DalNet.
Amidamaru

Amidamaru (статус: 4-ый класс), 1 июля 2008, 20:59 [#13]:

Мережников Андрей, мьютекс - потоко-зависимый объект. При завершении потока создавшего мьютекс и если нет других потоков, открывавших этот мьютекс то он уничтожается даже без CloseHandle.
Приглашаю Вас на наш IRC-канал: #delphiintru в сети DalNet.
Мережников Андрей

Мережников Андрей (статус: Абитуриент), 1 июля 2008, 21:11 [#14]:

Dart Mashiro посмотрите книгу Тома Свана "Секреты 32-разрядного программирования в Delphi" там есть такая фраза: Обычно следует проверить значение, возвращаемое функцией WaitForSingleObject. Значение WAIT_OBJECT_0 означает, что поток успешно получил доступ к мьютексу; а значение WAIT_ABANDONED означает, что поток, занимавший мьютекс, завершился, но сам мьютекс не был освобожден. и т.д.

Кстати, способ с FindWindow() работает даже со спрятанными окнами и приложениями. Проверено.
Amidamaru

Amidamaru (статус: 4-ый класс), 1 июля 2008, 21:22 [#15]:

Мережников Андрей, освобождение мьютекса и его уничтожение это 2 абсолютно разные вещи. Даже если поток, занимавший мьютекс, завершился, но сам мьютекс не был освобожден, этот мьютекс всёравно будет уничтожен, если нет других потоков, использующих этот мьютекс. CloseHandle - уничтожает объект. А освобождение мьютекса делается с помощью ReleaseMutex. Не стоит их путать.
Приглашаю Вас на наш IRC-канал: #delphiintru в сети DalNet.
Мережников Андрей

Мережников Андрей (статус: Абитуриент), 2 июля 2008, 07:16 [#16]:

Dart Mashiro Вы правы, сегодня все проверил.
"не верь глазам своим, пока не потрогаешь руками..." :-)
Мьютекс будет уничтожен по завершении последенего потока, который его использовал.
Мережников Андрей

Мережников Андрей (статус: Абитуриент), 2 июля 2008, 11:03 [#17]:

Но, на мой взгляд, лучше использовать FindWindow, поскольку изменения потребуется внести только в одно приложение - то, которое ждет. А вариант с мьютексами предполагает изменение обеих программ.

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 23 июля 2017, 05:52
Выполнено за 0.06 сек.
Рейтинг@Mail.ru