Delphi防止应用程序关闭 [英] Delphi prevent application shutdown

查看:136
本文介绍了Delphi防止应用程序关闭的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试防止我的应用程序被Windows关闭。
该应用程序在Windows 8上运行并用XE6编写。
我尝试了以下代码,但似乎被完全忽略了。为了测试它,我只是通过任务管理器发送结束任务给它。
我需要的是一种让应用程序在用户关闭,任务管理器或Windows关闭关闭时完成其操作的方法。
正常关闭不是问题,这由FormCloseQuery事件处理。但是我无法使用其他两种方法。在Windows XP之前,通过捕获wm_endsession和wm_queryendsession很容易,从vista开始,您需要使用ShutDownBlockReasonCreate,该函数返回true,但无论如何似乎都行不通。

I am trying to prevent my application from being shutdown by windows. The application is running on windows 8 and written in XE6. I tried following code but it seems to be completely ignored. To test it I simply send "end task" to it through the task manager. What I need is a way to let my application finish what its doing when the application is closed by the user, by the task manager of by a windows shutdown. Normal closing is not a problem, this is handled by the FormCloseQuery event. But the other 2 methods I can't get to work. Until windows XP this was easy by catching the wm_endsession and the wm_queryendsession, starting from vista you need the use ShutDownBlockReasonCreate, which returns true but does not seems to work anyway.

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;

更新

将消息结果更改为true并删除睡眠不会更改。

Changing the message result to true and removing the sleep changes nothing.

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;


推荐答案

根据文档要阻止关机,您需要返回 FALSE 来响应 WM_QUERYENDSESSION

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

此外,您不能在此消息处理程序中工作。这项工作必须在其他地方进行。如果您没有及时回复此消息,系统将不会等待您。

What's more, you must not do work in this message handler. The work must happen elsewhere. If you don't respond to this message in a timely fashion the system won't wait for you.


  • 在开始工作之前,请致电 ShutdownBlockReasonCreate

  • 工作时从 WM_QUERYENDSESSION 返回 FALSE 。处理此消息时请勿工作。立即返回。

  • 工作完成后,调用 ShutdownBlockReasonDestroy

  • Call ShutdownBlockReasonCreate before you start working.
  • Whilst working return FALSE from WM_QUERYENDSESSION. Don't work whilst handling this message. Return immediately.
  • When the work is done call ShutdownBlockReasonDestroy.

WM_QUERYENDSESSION 的处理程序看起来像这样:

The handler for WM_QUERYENDSESSION can look like this:

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

然后执行工作的代码需要调用 ShutdownBlockReasonCreate 工作开始之前, ShutdownBlockReasonDestroy 工作结束时,请确保上面使用的 Working 属性在工作期间评估为 True

And then the code that performs the work needs to call ShutdownBlockReasonCreate before the work starts, ShutdownBlockReasonDestroy when the work ends, and make sure that the Working property used above evaluates to True during work.

如果您的工作阻塞了主线程,那么您将遇到麻烦。主线程必须是响应性的,否则系统不会等待您。将工作放在一起通常是前进的道路。如果您的主窗口不可见,那么您就没有机会阻止关机。此处详细说明: http://msdn.microsoft.com/zh-cn /library/ms700677.aspx

If your work blocks the main thread then you are in trouble. The main thread must be responsive, otherwise the system won't wait for you. Putting the work in a thread is often the way forward. If your main window is not visible then you don't get a chance to block shutdown. The details are explained here: http://msdn.microsoft.com/en-us/library/ms700677.aspx

如果您被发送至 WM_ENDSESSION ,那么也是如此晚的。系统崩溃可能会发生什么。

If you get as far as being sent WM_ENDSESSION then it's too late. The system is going down come what may.


要对其进行测试,我只需通过任务管理器向其发送结束任务即可。

To test it I simply send "end task" to it through the task manager.

这与关闭阻止无关。测试关机阻止的方法是注销。如果用户坚持要终止您的进程,您将无能为力。 Sertac的答案对此进行了详细介绍。

That has nothing to do with shutdown blocking. The way you test shutdown blocking is to logoff. If the user insists on killing your process there is little that you can do about it. Sertac's answer covers this in detail.

最后,忽略API调用的返回值也是非常糟糕的形式。不要那样做

Finally, ignoring the return values of API calls is also very poor form. Don't do that.

这篇关于Delphi防止应用程序关闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆