2010-06-21 26 views
6

Do wykrywania i zapobiegania wyłączaniu komputera używam bardzo prostego programu. Ma tylko jeden formularz i jeden prywatny procedury jak poniżej:Zapobieganie zamykaniu systemu Windows

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

i realizację

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

Skompilowałem to Delphi 5 i Delphi 2010. Obaj wykryć wyłączył. Ale kiedy skompilowałem w Delphi 2010; po zablokowaniu mój program się zamyka. (Komputer się nie wyłącza)

Jak uzyskać taki sam wynik z obydwu?

+3

Czy mogę zapytać, dlaczego to robisz? zwykle jest niegrzeczne i nieuzasadnione zakłócanie zamykania. Poza tym ten rodzaj kodu wydaje się być kruchy i łamany z łatami bezpieczeństwa ... – MJB

+0

@MJB: Napisałem kiedyś taki program dla siebie - inny niegrzeczny program (Windows Update, IIRC) uważał, że można ponownie uruchomić komputer, za każdym razem, gdy odwróciłem się na chwilę. To była prawdopodobnie jakaś błędna konfiguracja WU, ale skoro nie mogłem tego naprawić, lub wyłączyć (przywileje i wszystkie), mogłem przynajmniej uniemożliwić mu pogrążanie się w pracy.(przy okazji, jest to udokumentowane i zgodne z prawem zachowanie od czasu WinXP, a główny cel komunikatu: "WM_QUERYENDSESSION" jest wysyłany do wszystkich aplikacji, aby sprawdzić, czy któryś z nich ma zastrzeżenia do wyłączenia - jeśli tak, wyłączenie zostanie przerwane) – Piskvor

Odpowiedz

0

To wygląda jak błąd w Delphi. Proponuję opublikować to w witrynie Quality Central.

+5

Już zgłosiłem to QC w zeszłym miesiącu: http://qc.codegear.com/wc/qcmain.aspx?d=84886 –

+0

Nie mogłem znaleźć poprawnej odpowiedzi na moje pytanie. Ale komentarz Remy'ego pokazał mi drogę. Co powinienem zrobić, aby przyjąć odpowiedź? – SimaWB

+0

Aby zaakceptować odpowiedź - potrzebujesz: 1. wybierz odpowiedź, aby zaakceptować. 2. kliknij biały \/"sprawdź" tuż poniżej głosów za odpowiedź. "Sprawdź" powinno stać się zielone - to znaczy, że ta odpowiedź została przyjęta (więc pytanie zostało rozwiązane). – Alex

0

Edytuj: Oto podejście, które nie działa. Dziękujemy

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

Nie " t, które uniemożliwiają zamknięcie aplikacji? –

+0

Niestety. Wypróbowano także zdarzenie OnCloseQuery. Ale mój program kończy się natychmiast. Nie wyzwala OnClose lub OnCloseQuery. – SimaWB

+8

@Uwe, SimbaWB, dziękuję za potwierdzenie, że to nie działa. Zastanowiłem się nad jego usunięciem, ale czasami warto zobaczyć, co nie działa. To jeden z takich przykładów. Nie przegłosuj proszę. Nie krępuj się. –

0

Czy testujesz w tym samym systemie operacyjnym? W systemie Vista są pewne zmiany w zamykaniu aplikacji. Przeczytaj to: Application Shutdown Changes in Windows Vista

Jeśli testujesz na tym samym systemie operacyjnym, być może Delphi 2010 obsługuje wiadomości WM_ENDSESSION w inny sposób. W Delphi 7 wiadomość WM_ENDSESSION jest obsługiwana w Application.WndProc.

+0

Testowałem te same systemy operacyjne (XP i Windows 7) – SimaWB

+0

@SimaWB: spróbuj dowiedzieć się, czy są jakieś różnice w obsłudze komunikatu WM_ENDSESSION między Delphi 5 a 2010 –

1

EDYCJA: zmieniono tak, aby przechwycić WM_ENDSESSION zamiast WM_QUERYENDSESSION.

Ponieważ nie można bezpośrednio zmienić działania programu TApplication, można zamiast tego zainstalować hak komunikatów TApplication, który neutralizuje komunikat WM_ENDSESSION.

Zainstalowanie takiego haka jest bardzo proste, wystarczy dodać do mainformu metodę podobną do poniższej i zarejestrować hak w 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

Plakat powiedział oba programy zapobiegły wyłączeniu, więc jego rozwiązanie działa, a hak nie jest potrzebny. Myślę, że problem leży w WM_ENDSESSION, który OS wysyła dalej. –

+0

Patrząc na odpowiedź Aleksandra i komentarz Remy'ego Lebeau, rzeczywiście jest to komunikat WM_ENDSESSION, który powoduje problemy. –

+0

Masz rację, WM_QUERYENDSESSION nie dociera do TApplication po wcześniejszym użyciu. Zaktualizowałem swoją odpowiedź, aby przechwycić WM_ENDSESSION za pomocą haka. –

0

We wszystkich wersjach nie należy używać zdarzenia FormCloseQuery?

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

Ups - tylko czytać komentarze do "to nie działa" :(Czy Win 7 różni

We wszystkich moich apps to dostaje zwanych jeśli okna stara się zamknąć ...

1
?

zwykle uruchomić polecenie "shutdown -a". można zrobić to samo z kodu przerwania Windows z wyłączenia.

Pozdrowienia

0

ShutdownGuard jest zbudowany z Delphi i jego open source, możesz go pobrać, dostosowując go do swoich potrzeb.

+0

Dzięki za link Mohammeda. Ale używa tej samej metody, którą napisałem powyżej. Problem nadal trwa ... – SimaWB

Powiązane problemy