WMQueryEndSession korrekt abfangen
spacer
Autor Nachricht
mcbain
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 55
Erhaltene Danke: 1



BeitragVerfasst: Di 15.11.11 17:17 
Hallo,
mein Programm soll in Aktion treten, sobald Windows die Message WMQueryEndSession sendet.
Ich habe dafür folgenden Code:

ausblenden Delphi-Quelltext markieren
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
procedure TForm1.WMQueryEndSession(var Msg: TWMQueryEndSession);
begin
if not bAllowShutdown then
begin
Msg.Result := 0;
Execute();
bAllowShutdown := True;
end;
if bAllowShutdown then
begin
Msg.Result := 1;
ExitWindowsEx(EWX_SHUTDOWN, $FFFFFFFF);
end;


end;


Über bAllowShutdown steuere ich das Verhalten, zu Beginn ist es immer False.
Execute() beinhaltet die eigentliche Aktion, es kopiert Ordner von links nach rechts.

Das Programm wird auch ausgeführt, jedoch meldet sich Windows und möchte das Programm "Sofort beenden".
Kann mir jemand bitte sagen was ich falsch mache?
Vielen DAnk.
Gruß
mc
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
Werbung ausblenden? Dann registriere Dich kostenlos. Weitere Gründe für eine Registrierung.


Werbung ausblenden? Dann registriere Dich kostenlos. Weitere Gründe für eine Registrierung.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starhalf offtopic star
Administrator
Beiträge: 8371
Erhaltene Danke: 244

W2k, WXPpro
TP3 - D7pro
BeitragVerfasst: Di 15.11.11 17:27 
Moin!

Hat deine Anwendung ein sog. "Top-Level-Window"? Wenn nicht, dann kommt diese Nachricht nie an, weil sie lt. MSDN nur an Top-Level-Windows gesendet wird! :idea: Hab da auch schonmal gebastelt... :roll:

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
mcbain Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 55
Erhaltene Danke: 1



BeitragVerfasst: Di 15.11.11 17:55 
Meine Anwendung hat ne ganz normale Form.
Die Nachricht kommt ja an bei meiner Anwendung. Er führt Execute() auch aus, da ich ja sehe, dass er die Dateien kopiert. Nur will Windows irgendwann währenddessen die Anwendung beenden.
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Moderator
Beiträge: 8118
Erhaltene Danke: 251

Win XP, Win 7
D7 PE, RAD Studio 2009 Professional
BeitragVerfasst: Di 15.11.11 18:18 
Diese Message sollte sehr schnell beantwortet werden, sieh auch MSDN dazu. Besser wäre wohl direkt an Windows das ok zu liefern, und dann mit dem Aufräumen anzufangen. Das sollte dann so ziemlich erledigt sein, wenn kurz danach die WM_ENDSESSION kommt.

_________________
Oel ngati kameie.


Zuletzt bearbeitet von Gausi am Di 15.11.11 18:21, insgesamt 1-mal bearbeitet
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
mcbain Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 55
Erhaltene Danke: 1



BeitragVerfasst: Di 15.11.11 18:21 
Aber die Message wird doch schnell beantwortet.
Sobald die Message von Windows kommt, wird Msg.Result := 0 gestzt. Erst danach führe ich meine Execute Methode aus.
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
Luckie
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starhalf offtopic starofftopic star
Beiträge: 11803
Erhaltene Danke: 146

WindowsXP Professional SP2
BDS2006, VS C++ Express, Eclipse (Java), Flex (Flash, AS)
BeitragVerfasst: Di 15.11.11 18:32 
Und wie lange dauert die Aktion? Ab Windows Vista (oder schon ab XP) ist da Windows etwas ungeduldiger geworden, um es mal vorsichtig auszudrücken.

_________________
Gruß Michael
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
mcbain Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 55
Erhaltene Danke: 1



BeitragVerfasst: Di 15.11.11 18:52 
Das ist verschieden. Die Aktion kann schon paar Minuten brauchen. Müssen ja Ordner kopiert werden.
Derzeit führe ich es unter WinXP aus.
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 15841
Erhaltene Danke: 741

XP, W7 x64 (Chrome, IE9, FF), Debian, (OSX 10.7)
RAD XE 2, Java (NB), C++, C# (VS 2010), JS/HTML, PHP, Lazarus
BeitragVerfasst: Di 15.11.11 19:05 
user profile iconmcbain hat folgendes geschrieben Zum zitierten Posting springen:
Aber die Message wird doch schnell beantwortet.
Sobald die Message von Windows kommt, wird Msg.Result := 0 gestzt. Erst danach führe ich meine Execute Methode aus.
:lol:
Naja, aber Windows hat ja die Antwort noch nicht. Du blockierst ja mit deinem Execute die Rückgabe des Ergebnisses, das du nur in den Speicher des Records geschrieben hast. Das ist als ob du eine Anfrage per Fax bekommst und dann die Antwort direkt aufschreibst, aber erst am Feierabend rausschickst.

Du musst aus der Messagebehandlung sofort raus und die Aktion danach ausführen, damit Windows deine Antwort schon hat.

Zum Zweiten solltest du Windows (ab Vista) mit ShutdownBlockReasonCreate usw. mitteilen, dass es noch warten soll und was es dem Benutzer als Grund anzeigen soll, dass dein Programm noch nicht beendet werden möchte.
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
mcbain Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 55
Erhaltene Danke: 1



BeitragVerfasst: Di 15.11.11 19:20 
Alles klar, an dem lags. Man muss so schnell es geht aus der procedure raus.
Ich starte jetzt einfach einen timer innerhalb der Message. Dieser übernimmt dann anschließend das Kopieren.

Vielen Dank für eure Anregungen.
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 15841
Erhaltene Danke: 741

XP, W7 x64 (Chrome, IE9, FF), Debian, (OSX 10.7)
RAD XE 2, Java (NB), C++, C# (VS 2010), JS/HTML, PHP, Lazarus
BeitragVerfasst: Di 15.11.11 21:26 
user profile iconmcbain hat folgendes geschrieben Zum zitierten Posting springen:
Ich starte jetzt einfach einen timer innerhalb der Message. Dieser übernimmt dann anschließend das Kopieren.
Und was macht ein Timer? Du sagst damit Windows Bescheid, dass du alle x Millisekunden eine Windows Message haben willst. Die empfängt dann der Timer und sagt dir per Event Bescheid...

Warum schickst du dir nicht direkt mit PostMessage eine Message und sparst dir das ganze Drumherum mit dem Timer?
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
Andreas L.
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starhalf offtopic starofftopic starofftopic star
Beiträge: 1671
Erhaltene Danke: 14

Windows Vista Home Premium 32Bit
RAD Studio 2009 Pro
BeitragVerfasst: Mi 16.11.11 12:15 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:


Zum Zweiten solltest du Windows (ab Vista) mit ShutdownBlockReasonCreate usw. mitteilen, dass es noch warten soll und was es dem Benutzer als Grund anzeigen soll, dass dein Programm noch nicht beendet werden möchte.


Ich wollte das mal ausprobieren. Also habe ich die nötigen Methoden deklariert:
ausblenden Delphi-Quelltext markieren
1:
2:
  function ShutdownBlockReasonCreate(hWnd: HWND; pwszReason: LPCWSTR): Bool; external user32 name 'ShutdownBlockReasonCreate';
function ShutdownBlockReasonDestroy(hWnd: HWND): Bool; external user32 name 'ShutdownBlockReasonDestroy';


Per Button-Klick wollte ich es verwenden:
ausblenden Delphi-Quelltext markieren
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
procedure TForm2.Button1Click(Sender: TObject);
begin
if ShutdownBlockReasonCreate(Handle, 'Test') then
ListBox1.Items.Add('Shutdown-Block aktiv')
else
ListBox1.Items.Add('Shutdown-Block konnte nicht aktiviert werden!');
end;

procedure TForm2.Button2Click(Sender: TObject);
begin
if ShutdownBlockReasonDestroy(Handle) then
ListBox1.Items.Add('Shutdown-Block deaktiviert')
else
ListBox1.Items.Add('Shutdown-Block konnte nicht deaktiviert werden!');
end;


Die Funktion ShutdownBlockReasonCreate gibt aber immer False zurück und das Herunterfahren wird nicht blockiert. Auch wenn ich die Anwendung außerhalb der IDE sowie mit Admin-Rechten starte funktioniert es nicht. Habe ich die Funktionen falsch eingebunden oder was mache ich falsch?

EDIT: GetLastError liefert 0 also kein Fehler.
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 15841
Erhaltene Danke: 741

XP, W7 x64 (Chrome, IE9, FF), Debian, (OSX 10.7)
RAD XE 2, Java (NB), C++, C# (VS 2010), JS/HTML, PHP, Lazarus
BeitragVerfasst: Mi 16.11.11 17:10 
Da fehlt das std_call bei den Deklarationen.
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
Andreas L.
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starhalf offtopic starofftopic starofftopic star
Beiträge: 1671
Erhaltene Danke: 14

Windows Vista Home Premium 32Bit
RAD Studio 2009 Pro
BeitragVerfasst: Fr 18.11.11 13:40 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Da fehlt das std_call bei den Deklarationen.


Jetzt wird der in der ListBox zwar Shutdown-Block aktiv ausgegeben. Der PC fährt allerdings trotzdem ohne jegliche Meldung herunter. Hast du eine Idee was falsch läuft?

ausblenden volle Höhe Delphi-Quelltext markieren
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
  function ShutdownBlockReasonCreate(hWnd: HWND; pwszReason: LPCWSTR): Bool; stdcall; external user32 name 'ShutdownBlockReasonCreate';
function ShutdownBlockReasonDestroy(hWnd: HWND): Bool; stdcall; external user32 name 'ShutdownBlockReasonDestroy';

...

procedure TForm2.Button1Click(Sender: TObject);
var
error: Cardinal;
begin
if ShutdownBlockReasonCreate(Form2.Handle, 'Test') then
ListBox1.Items.Add('Shutdown-Block aktiv')
else
begin
ListBox1.Items.Add('Shutdown-Block konnte nicht aktiviert werden!');
if GetLastError <> ERROR_SUCCESS then
begin
error := GetLastError;
end;
//ListBox1.Items.Add('GetLastError:' + IntToStr(GetLastError));
end;
end;

procedure TForm2.Button2Click(Sender: TObject);
begin
if ShutdownBlockReasonDestroy(Handle) then
ListBox1.Items.Add('Shutdown-Block deaktiviert')
else
begin
ListBox1.Items.Add('Shutdown-Block konnte nicht deaktiviert werden!');
ListBox1.Items.Add('GetLastError:' + IntToStr(GetLastError));
end;
end;
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 15841
Erhaltene Danke: 741

XP, W7 x64 (Chrome, IE9, FF), Debian, (OSX 10.7)
RAD XE 2, Java (NB), C++, C# (VS 2010), JS/HTML, PHP, Lazarus
BeitragVerfasst: Fr 18.11.11 14:42 
Die QueryEndSession Message musst du aber dennoch entsprechend beantworten, sonst beachtet Vista/7 deinen registrierten Blockiergrund gar nicht.
 
Antworten mit Zitat Beitrag melden
Private Nachricht sendenPosting in privater Nachricht zitieren
home home