2010-06-21 3 views
6

Чтобы обнаружить и предотвратить выключение компьютера, я использую очень простую программу. Она имеет только одну форму и одной частной процедуры, как показано ниже:Предотвращение закрытия Windows

TForm3 = class(TForm) 
private 
    procedure WMQueryEndSession(var Msg : TWMQueryEndSession) ; 
     message WM_QueryEndSession; 
end; 

и реализацию

procedure TForm3.WMQueryEndSession(var Msg: TWMQueryEndSession); 
begin 
    Msg.Result := 0; //so I don't want to shutdown while my program is running 
end; 

Я составил его Delphi 5 и Delphi 2010. Оба обнаружить завершение работы. Но когда я собрал в Delphi 2010; после предотвращения отключения моя программа закрывается. (ПК не выключается)

Как получить тот же результат от обоих?

+3

Могу ли я спросить, почему вы это делаете? обычно грубо и необоснованно вмешиваться в выключение. Плюс этот тип кода имеет тенденцию быть хрупким и ломается с патчами безопасности ... – MJB

+0

@MJB: Однажды я написал такую ​​программу для себя - еще одна грубая программа (Windows Update, IIRC) подумала, что было нормально перезагружать компьютер, каждый раз, когда я повернулась спиной на минуту. Вероятно, это была некорректная конфигурация WU, но поскольку я не мог ее исправить или отключить (привилегии и все), я мог бы по крайней мере предотвратить ее из-за моей работы.(Кстати, это документированное и законное поведение с WinXP и основная цель сообщения: 'WM_QUERYENDSESSION' отправляется во все приложения, чтобы узнать, есть ли у кого-либо из них возражение на завершение работы - если это так, выключение прерывается) – Piskvor

ответ

0

Это похоже на ошибку в Delphi. Я предлагаю вам опубликовать это на Quality Central.

+5

Я уже сообщал об этом в QC в прошлом месяце: http://qc.codegear.com/wc/qcmain.aspx?d=84886 –

+0

Я не смог найти правильный ответ на мой вопрос. Но комментарий Реми показал мне дорогу. Итак, что я должен сделать для принятия ответа? – SimaWB

+0

Для получения ответа - вам нужно: 1. выбрать ответ для принятия. 2. Нажмите на белый \/"проверить" чуть ниже голосов за ответ. «Проверить» должен стать зеленым - это будет означать, что этот ответ был принят (поэтому вопрос был решен). – Alex

0

Редактировать: Вот подход, который не работает. Спасибо

Procedure TMyForm.FormClose(Sender: TObject; Var Action: TCloseAction); 
Begin 
    Action := caNone; //The form is not allowed to close, so nothing happens. 
End;     // Note: the OP says he tried this, doesn't help. See the comments. 
+0

. t, которые вообще не позволяют закрыть приложение? –

+0

к сожалению. Также проверено событие OnCloseQuery. Но моя программа немедленно закрывается. Не запускать OnClose или OnCloseQuery. – SimaWB

+8

@Uwe, SimbaWB, спасибо за подтверждение, что это не сработает. Я думал об удалении его, но иногда полезно видеть, что не работает. Это один из таких примеров. Не подпирайте, пожалуйста. Не стесняйтесь. –

0

Вы тестируете на той же ОС? В Vista есть некоторые изменения завершения работы приложения. Прочтите это: Application Shutdown Changes in Windows Vista

Если вы тестируете на той же ОС, возможно, Delphi 2010 обрабатывает сообщения WM_ENDSESSION по-другому. В Delphi 7 сообщение WM_ENDSESSION обрабатывается в Application.WndProc.

+0

Я тестировал те же ОС (XP и Windows 7) – SimaWB

+0

@SimaWB: попытайтесь выяснить, есть ли какие-либо различия в обработке сообщения WM_ENDSESSION между Delphi 5 и 2010 –

1

EDIT: изменено на перехват WM_ENDSESSION вместо WM_QUERYENDSESSION.

Поскольку вы не можете напрямую изменить поведение TApplication, вместо этого вы можете установить крючок сообщения TApplication, который нейтрализует сообщение WM_ENDSESSION.

Установка такого крючка довольно проста, вам нужно добавить к вашей основной форме метод, аналогичный приведенному ниже, и зарегистрировать крючок в FormCreate.

function TForm25.HookEndSession(var Message: TMessage): Boolean; 
begin 
    result := false; 
    if Message.Msg = WM_ENDSESSION then begin 
    Message.Result := 0; 
    result := true; 
    end; 
end; 

procedure TForm25.FormCreate(Sender: TObject); 
begin 
    Application.HookMainWindow(HookEndSession); 
end; 
+1

Плакат сказал обе программы предотвратили выключение, поэтому его решение работает, и крючок не нужен. Я думаю, проблема связана с WM_ENDSESSION, которую ОС отправляет дальше. –

+0

Рассматривая ответ Александра и комментарий Реми Лебо, это сообщение WM_ENDSESSION, которое вызывает проблемы. –

+0

Вы правы, WM_QUERYENDSESSION не достигает TApplication при обращении до этого. Я обновил свой ответ, чтобы перехватить WM_ENDSESSION с помощью hook. –

0

Во всех версиях вы не должны использовать событие FormCloseQuery?

procedure TForm3.FormCloseQuery(Sender: TObject; var CanClose: Boolean); 
begin 
    Canclose := Not StillDoingImportantStuff; 
end; 

Упс - просто прочитать комментарии к «это не работает» :(Является ли выиграть 7 разные

Во всех моих приложениях это вызывается, если окна пытаются закрыть ...

1
?

Я обычно запустить команду «выключение -a». Вы можете сделать то же самое из кода прерывания Windows, от остановки.

с уважением

0

ShutdownGuard является построенный с помощью Delphi, и это с открытым исходным кодом, вы можете скачать его для своих нужд.

+0

Спасибо за ссылку Мохаммед. Но он использует тот же метод, который я написал выше. Поэтому проблема продолжается ... – SimaWB