views:

431

answers:

7

To detect and prevent shutdown the computer I use very simple program. It has only one form and one private procedure like below:

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

and the implementation

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

I compiled it Delphi 5 and Delphi 2010. Both of them detect shutdown. But when I compiled in Delphi 2010; after preventing shutdown my program closes. (PC doesn't shutdown)

How do I get the same result from both of them?

A: 

Edit: Here's an approach that doesn't work. Thanks

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.
Chris Thornton
Wouldn't that prevent to close the app anyway?
Uwe Raabe
unfortunately. Also tried OnCloseQuery event. But my program closes immediately. Not trigger OnClose or OnCloseQuery.
SimaWB
@Uwe, SimbaWB, thanks for confirming that this doesn't work. I thought about deleting it, but it is sometimes helpful to see what doesn't work. This is one such example.. Don't upvote please. Feel free to downvote.
Chris Thornton
@Chris, Not upvote for your answer but upvote the comment ;)
SimaWB
A: 

Are you testing on the same OS? There are some application shutdown changes in Vista. Read this: Application Shutdown Changes in Windows Vista

If you are testing on the same OS, maybe Delphi 2010 handles WM_ENDSESSION messages in a different way. In Delphi 7, WM_ENDSESSION message are handled in Application.WndProc.

The_Fox
I tested same OSs (XP and Windows 7)
SimaWB
@SimaWB: try to find out if there are any differences in handling the WM_ENDSESSION message between Delphi 5 and 2010
The_Fox
A: 

EDIT: changed to intercept WM_ENDSESSION instead of WM_QUERYENDSESSION.

As you cannot directly change the behaviour of TApplication, you can install a Windows hook instead that neutralizes the WM_ENDSESSION message.

Installing such a hook is quite simple, you only have to add a method similar to the following to your mainform and register the hook in 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;
Uwe Raabe
The poster said both programs prevented shutdown, so his solution works and a hook isn't needed. I think the problem lies with the WM_ENDSESSION that the OS sends next.
The_Fox
Looking at Alexander's answer and the comment of Remy Lebeau it is indeed the WM_ENDSESSION message that is causing problems.
The_Fox
You are right, the WM_QUERYENDSESSION doesn't reach TApplication when handled before. I have updated my answer to intercept WM_ENDSESSION with a hook.
Uwe Raabe
A: 

This looks like a bug in Delphi. I suggest you to post this on Quality Central.

Alexander
I already reported this to QC last month: http://qc.codegear.com/wc/qcmain.aspx?d=84886
Remy Lebeau - TeamB
I couldn't find the correct answer of my question. But Remy's comment was showed me the way. So what should I do for accepting an answer?
SimaWB
For accepting answer - you need: 1. select an answer to accept. 2. click on white \/ "check" just below votes for answer. "Check" should become green - this will mean that this answer was accepted (so the question was solved).
Alexander
Alexander, really do you think I don't know that :) I want to tell that; your answer is not correct answer of the question. But Remy's comment was very helpful for me.
SimaWB
Sorry, I didn't understand you.
Alexander
A: 

In all versions should you not be using the FormCloseQuery event?

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

Oops - just read comments to "this does not work" :( Is win 7 different?

In all my apps this gets called if windows is trying to shut down...

Despatcher
+1  A: 

Hello,

I usually run "shutdown -a" command. You can do the same from your code to interrupt Windows from shutdown.

Regards

opal
A: 

ShutdownGuard is built with Delphi and it's open source, you can download it tweak it for your needs

Mohammed Nasman
Thanks for the link Mohammed. But it uses the same method which I have written above. So the problem continues...
SimaWB