Форум: "Начинающим";
Текущий архив: 2006.01.22;
Скачать: [xml.tar.bz2];
ВнизКорректное завершение работы программы при выключении ПК Найти похожие ветки
← →
azl © (2005-12-29 11:40) [0]Привет, всем.
Подскажите, пожалуйста, как корректно завершить работу программы при выключении компьютера? Понятно, что можно закрыть вручную, но, мне нужно чтобы программа корректно завершала свою работу, находясь запущенной с трее (в моем случае), когда делается завершение работы Windows или перезагрузка.
Я нашел в инете, следующее:
Application.Terminated := true
А вот где это писать? OnDestroy?
Или может как-то по-другому?
Спасибо.
← →
Dmitrij_K (2005-12-29 11:49) [1]Очень часто мы сталкиваемся с проблемой, когда наша программа будучи запущенная в фоне и/или свёрнутая, например, в панель задач должна что-то сделать, когда Windows выключается, перезагружается или просто меняется пользователь.
Если мы не будем отслеживать такую ситуацию, то в худшем случае у нас могут просто потеряться какие-либо данные или Windows просто не сможет выполнить перезагрузку до конца. Ей будет мешать наша программа. Не нужно думать, что Windows перед перезагрузкой рассылает приложениям сообщения о закрытии, так чтобы у тех выпаолнились обработчкики TForm.onCloseQuery/onClose.
ОС Windows отсылает перед перезагрузкой, выключением или сменой пользователя сообщения WM_QUERYENDSESSION, а потом по его успешному завершению WM_ENDSESSION. Наше приложение должно поймать эти сообщения и отреагировать так чтобы дать понять, что мы согласны перезагружаться. В частности на сообщение WM_QUERYENDSESSION мы должны вернуть не 0:
The WM_QUERYENDSESSION message is sent when the user chooses to end the Windows session or when an application calls the ExitWindows function. If any application returns zero, the Windows session is not ended. Windows stops sending WM_QUERYENDSESSION messages as soon as one application returns zero.
Практически мы уже здесь можем завершить свою программу.
В случае если те действия, которые выполняются при наступлении перезагрузки не велики по величине времени их выполнения, можно не обрабатывать WM_QUERYENDSESSION, а обойтись просто сообещением WM_ENDSESSION. В параметре WParam этого сообщения поступает как раз тот результат, который мы вернули (или не вернули) из сообщения WM_QUERYENDSESSION:
protectedprocedure IsWindowsShutDown(var Msg: TMessage);WM_ENDSESSION;
..
procedure TForm1.IsWindowsShutDown(var Msg: TMessage);
begin
inherited;
if Msg.WParam = 1 then MainForm.Close; // выгружаем приложение
End;
Если нам нужно что-то сделать ещё (например удалить какой-либо файл или записать какую-нибудь информацию), применительно для вышеприведённого примера это можно сделать в обработчиках onCloseQuery/onClose формы.
Процедуру IsWindowsShutDown() мы должны описать в классе того окна, которое будет принимать данное сообщение т.е. формы.
Автор: Song
http://www.drkb.ru
← →
azl © (2005-12-29 12:49) [2]Спасибо
protected procedure IsWindowsShutDown(var Msg: TMessage);WM_ENDSESSION;
Ругается на WM_ENDSESSION;
Пишет: Field definition not allowed after methods or properties
И, наверное, вместо MainForm.Close; Нужно писать Form1.Close; ?
Без WM_ENDSESSION; запускается.
← →
Dmitrij_K (2005-12-29 13:07) [3]Тут помоему опечатка
должно быть так
protected
procedure IsWindowsShutDown(var Msg: TMessage); message WM_ENDSESSION;
← →
azl © (2005-12-29 14:02) [4]Это не работает.
У меня напоминалка с базой Paradox. Добавляю новую запись, делаю завершение сеанса пользователя, при этом программа запущена, загружаюсь запускаю программу записи нет. А если руками закрыть программу и сделать завершение сеанса пользователя. Все нормально.
← →
Digitman © (2005-12-29 14:13) [5]
> Это не работает
это РАБОТАЕТ.
будучи примененным не от балды и с полным пониманием происходящего
← →
azl © (2005-12-29 14:36) [6]Я извиняюсь, но может я что-то неправильно сделал. В моей ситуации не работает. Если не затруднит, скажите, что я делаю не так.
Спасибо.
← →
Digitman © (2005-12-29 14:43) [7]если не ошибаюсь, следует обрабатывать событие Application.OnMessage, в коем собссно и анализировать поступающие сообщения на предмет обнаружения WM_QUERYENDSESSION
← →
azl © (2005-12-29 14:54) [8]А пример можно?
← →
Digitman © (2005-12-29 14:58) [9]туеву хучу оных найдешь, набрав "Delphi WM_QUERYENDSESSION" в кач-ве модели поиска в Гугле
← →
evvcom © (2005-12-29 15:45) [10]угу, а еще
> Добавляю новую запись, делаю завершение сеанса пользователя,
> при этом программа запущена, загружаюсь запускаю программу
> записи нет.
надо проанализировать, а не находится ли набор в состоянии dsEdit или dsInsert и если да, то Post не забыть. А то Close сам тебе Post не сделает. :)
← →
azl © (2005-12-29 16:31) [11]
> evvcom ©
Нет, везде Post стоит. Я так понял, это у Paradox"a такая особенность, если некорректно завершаешь работу программы, например, через Ctrl+Alt+Del, то записи не сохраняются.
← →
Германн © (2005-12-29 16:49) [12]DBISaveChanges могут помочь отцу русской демократии.
← →
evvcom © (2005-12-29 16:50) [13]
> если некорректно завершаешь работу программы
а при чем тут парадокс? Пока post не сделал, запись в буфере редактирования еще лежит. Когда сделал, может попасть в кеш компонента доступа к БД, если кеш используется. Потом еще у движка свой кеш имеется. Не будет же движок при каждом твоем чихе жесткий диск дергать!
> Нет, везде Post стоит
Тогда только Digitman © (29.12.05 14:43) [7] вроде остается.
← →
azl © (2005-12-29 17:13) [14]Вот нашел выход:
unit Unit1;
interface
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm1 = class(TForm)
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
procedure WMQueryEndSession(
var Message: TWMQueryEndSession); message WM_QUERYENDSESSION;
public
{ Public declarations }
end;
var
Form1 : TForm1;
implementation
{$R *.DFM}
procedure TForm1.WMQueryEndSession(var Message: TWMQueryEndSession);
begin
inherited;
Form1.Close;
end;
http://www.i2n.ru/article/print.php?id=19
Вроде бы помогло.
← →
Leonid Troyanovsky © (2005-12-29 18:13) [15]
> azl © (29.12.05 17:13) [14]
Достаточно было б просто поместить код корректного завершения
в обработчик OnCloseQuery формы.
Корректного в сысле: сделать необходимые действия по сохранению
нужного, но не Application.Terminate, который сделают и без нас.
--
Regards, LVT.
← →
Германн © (2005-12-30 02:09) [16]А я - так вообще ничего не понял. Что именно помогло автору.
А по поводу
> Leonid Troyanovsky © (29.12.05 18:13) [15]
>
>
> > azl © (29.12.05 17:13) [14]
>
>
> Достаточно было б просто поместить код корректного завершения
> в обработчик OnCloseQuery формы.
можно высказаться?
Имхо, OnCloseQuery позволяет отменить закрытие приложения, но не гарантирует нормальную работу его в случае отмены закрытия, если оно вызвано выключением/перезагрузкой/сменой пользователя. Поскольку какие-то другие приложения/процессы уже могут быть отключены. Я вообще не знаю - известен ли порядок отключения процессов при выключении/перезагрузке и т.д?
Так что лучше поместить код корректного завершения в обработчик OnClose формы. Имхо.
← →
Leonid Troyanovsky © (2005-12-30 11:12) [17]
> Германн © (30.12.05 02:09) [16]
> А я - так вообще ничего не понял. Что именно помогло автору.
Видимо, код завершения находится в OnClose, поэтому
потребовалось вызывать принудительно Close.
> Имхо, OnCloseQuery позволяет отменить закрытие приложения,
> но не гарантирует нормальную работу его в случае отмены
> закрытия, если оно вызвано выключением/перезагрузкой/сменой
Дык, зачем отменять закрытие, если оно вызвано перезагрузкой?
Просто, с отменой закрытия надо быть аккуратней - from Forms:
procedure TCustomForm.WMQueryEndSession(var Message: TWMQueryEndSession);
begin
Message.Result := Integer(CloseQuery and CallTerminateProcs);
end;
Т.е., такому как Delphi help: TCustomForm.OnCloseQuery example -
место в корзине.
--
Regards, LVT.
← →
Германн © (2005-12-31 02:34) [18]2 Leonid Troyanovsky © (30.12.05 11:12) [17]
А причём тут пример из справки?
Суть то ведь в том, имхо, что нужны одновременно две вещи.
1. Переспросить пользователя - "действительно ли он хочет закрыть своё приложение, если он/оно что-то не доделал/доделело?" Если этот самый пользователь пытается закрыть это приложение, то - отмена закрытия, имхо, вполне нормальное решение.
2. Приложение может быть закрыто при презагрузке ОС/смене пользователя/перезагрузке компьютера. А вот тут - совершенно непонятно как быть?
← →
Leonid Troyanovsky © (2006-01-01 14:27) [19]
> Германн © (31.12.05 02:34) [18]
> 2 Leonid Troyanovsky © (30.12.05 11:12) [17]
> А причём тут пример из справки?
Потому, что это пример как не надо делать обработчик OnCloseQuery.
> 2. Приложение может быть закрыто при презагрузке ОС/смене
> пользователя/перезагрузке компьютера. А вот тут - совершенно
> непонятно как быть?
Например,
http://groups.google.com/group/fido7.ru.delphi.chainik/msg/308deb5e10abdcbb
Пожалуй, только вместо msg.Result := LParam(True);
точнее inherited.
--
Regards, LVT.
← →
Германн © (2006-01-02 02:32) [20]2 Leonid Troyanovsky © (01.01.06 14:27) [19]
> Например,
>
> http://groups.google.com/group/fido7.ru.delphi.chainik/msg/308deb5e10abdcbb
Нет. Я не про то, как отличить один вид завершения программы от другого, а про то, что при завершении программы самим пользователем, завершается лишь она сама. А при завершении Windows каким-либо способом, завершается часть процессов на данный момент работающих, в том числе и моего. В своей программе я могу отменить это завершение. Но что делать, если уже самой системой завершены один или несколько процессов, которые мне нужны для работы?
← →
Leonid Troyanovsky © (2006-01-03 15:30) [21]
> Германн © (02.01.06 02:32) [20]
> программе я могу отменить это завершение. Но что делать,
> если уже самой системой завершены один или несколько процессов,
> которые мне нужны для работы?
Проще сразу завершиться.
В конце-концов, это не такой большой грех, как отказ при логофе.
--
Regards, LVT.
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2006.01.22;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.051 c