6

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?

Raidri
  • 17,258
  • 9
  • 62
  • 65
SimaWB
  • 9,246
  • 2
  • 41
  • 46
  • 3
    May I ask why you are doing this? usually it is rude and unwarranted to interfere with shutdown. Plus this kind of code tends to be fragile and break with security patches... – MJB Jun 30 '10 at 23:13
  • @MJB: I wrote such program for myself once - another rude program (Windows Update, IIRC) thought it was OK to reboot the computer, every time I turned my back for a minute. It was probably some misconfiguration of WU, but since I couldn't fix it, or turn it off (privileges and all), I could at least prevent it from gobbling up my work. (btw, this is documented and legitimate behavior since WinXP, and the primary purpose of the message: `WM_QUERYENDSESSION` is sent to all apps to see if any of them has an objection to shutdown - if so, shutdown is aborted) – Piskvor left the building Jul 03 '10 at 16:59

7 Answers7

2

EDIT: changed to intercept WM_ENDSESSION instead of WM_QUERYENDSESSION.

As you cannot directly change the behaviour of TApplication, you can install a TApplication message 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;
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
Uwe Raabe
  • 45,288
  • 3
  • 82
  • 130
  • 1
    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 Jun 21 '10 at 20:17
  • Looking at Alexander's answer and the comment of Remy Lebeau it is indeed the WM_ENDSESSION message that is causing problems. – The_Fox Jun 21 '10 at 20:20
  • 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 Jun 22 '10 at 06:48
1

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

Regards

opal
  • 143
  • 1
  • 6
0

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
  • 15,620
  • 5
  • 37
  • 62
  • Wouldn't that prevent to close the app anyway? – Uwe Raabe Jun 21 '10 at 14:19
  • unfortunately. Also tried OnCloseQuery event. But my program closes immediately. Not trigger OnClose or OnCloseQuery. – SimaWB Jun 21 '10 at 14:19
  • 8
    @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 Jun 21 '10 at 14:30
0

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
  • 6,992
  • 2
  • 43
  • 69
0

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

Alex
  • 5,477
  • 2
  • 36
  • 56
  • 5
    I already reported this to QC last month: http://qc.codegear.com/wc/qcmain.aspx?d=84886 – Remy Lebeau Jun 21 '10 at 20:13
  • 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 Jul 09 '10 at 15:12
  • 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). – Alex Jul 09 '10 at 17:51
  • 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 Jul 13 '10 at 06:45
  • Sorry, I didn't understand you. – Alex Jul 13 '10 at 09:18
0

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,745
  • 12
  • 18
0

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

Mohammed Nasman
  • 10,992
  • 7
  • 43
  • 68
  • Thanks for the link Mohammed. But it uses the same method which I have written above. So the problem continues... – SimaWB Jun 24 '10 at 07:11