Delphi prevents application closure

I am trying to prevent my Windows application from starting. The application runs on windows 8 and is written in XE6. I tried the following code, but it seems to be completely ignored. To test this, I simply send him the "final task" through the task manager. I need my application to complete what it does when the application is closed by the user, task manager, when Windows shuts down. Normal closure is not a problem, it is due to the FormCloseQuery event. But the other 2 methods that I cannot work with. Prior to Windows XP, this was easy, having caught wm_endsession and wm_queryendsession, starting with vista you need to use ShutDownBlockReasonCreate, which returns true but doesn't seem to work.

procedure WMQueryEndSession(var Msg : TWMQueryEndSession); message WM_QUERYENDSESSION; procedure WMEndSession(var Msg: TWMEndSession); message WM_ENDSESSION; function ShutdownBlockReasonCreate(hWnd: HWND; Reason: LPCWSTR): Bool; stdcall; external user32; function ShutdownBlockReasonDestroy(hWnd: HWND): Bool; stdcall; external user32; procedure TForm1.WMEndSession(var Msg: TWMEndSession); begin inherited; Msg.Result := lresult(False); ShutdownBlockReasonCreate(Handle, 'please wait while muting...'); Sleep(45000); // do your work here ShutdownBlockReasonDestroy(Handle); end; procedure TForm1.WMQueryEndSession(var Msg: TWMQueryEndSession); begin inherited; Msg.Result := lresult(False); ShutdownBlockReasonCreate(Handle, 'please wait while muting...'); Sleep(45000); // do your work here ShutdownBlockReasonDestroy(Handle); end; 

Update

Changing the message result to true and deleting sleep mode does not change anything.

 procedure TForm1.WMEndSession(var Msg: TWMEndSession); begin inherited; Msg.Result := lresult(True); ShutdownBlockReasonDestroy(Application.MainForm.Handle); ShutdownBlockReasonCreate(Application.MainForm.Handle, 'please wait while muting...'); end; procedure TForm1.WMQueryEndSession(var Msg: TWMQueryEndSession); begin inherited; Msg.Result := lresult(True); ShutdownBlockReasonDestroy(Application.MainForm.Handle); ShutdownBlockReasonCreate(Application.MainForm.Handle, 'please wait while muting...'); end; 
+5
source share
2 answers

According to the documentation, to disable the shutdown, you need to return FALSE in response to WM_QUERYENDSESSION .

What else, you should not work in this message handler. Work must take place elsewhere. If you do not reply to this message in a timely manner, the system will not wait for you.

  • Call ShutdownBlockReasonCreate before you get started.
  • At run time, return FALSE from WM_QUERYENDSESSION . Do not work with this message. Come back immediately.
  • When you are done, call ShutdownBlockReasonDestroy .

The handler for WM_QUERYENDSESSION might look like this:

 procedure TMainForm.WMQueryEndSession(var Msg: TWMQueryEndSession); begin if Working then Msg.Result := 0 else inherited; end; 

And then the code that does the work should call ShutdownBlockReasonCreate before it starts, ShutdownBlockReasonDestroy when the job is done, and make sure that the Working property above is evaluated as True at run time.

If your work blocks the main thread, you are having problems. The main thread must respond, otherwise the system will not wait for you. Putting work on stream is often a way forward. If your main window does not appear, you cannot block the shutdown. Details are explained here: http://msdn.microsoft.com/en-us/library/ms700677.aspx

If you get to sending WM_ENDSESSION , then it's too late. The system goes down that it can.

To test this, I just send him the "final task" through the task manager.

This has nothing to do with shutdown lock. The way you check the shutdown lock is to log out. If the user insists on killing your process, little can be done. Sertac's answer details this.

Finally, ignoring the return values ​​of API calls is also very bad. Do not do that.

+8
source

Your code seems to be completely ignored because you are not testing it. You send him the "final task" through the task manager, the code you published is only effective when the system closes.

Unlike Windows 8, how the task manager works. Before Windows 8, the final task from the task manager will first try to close the application gracefully (sends WM_CLOSE ), with which you are working with OnCloseQuery . But when the application denies closing, the task manager will prompt you to complete the process. It's impossible. The same thing if you select the "final process" from the task manager.

Windows 8 Task Manager does not offer an additional dialog box to force the application to close, but does so immediately when the application refuses to close.

+6
source

Source: https://habr.com/ru/post/1201274/


All Articles