加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Delphi阻止应用程序关闭

发布时间:2020-12-15 09:49:20 所属栏目:大数据 来源:网络整理
导读:我试图阻止我的应用程序被 Windows关闭. 该应用程序在Windows 8上运行并以XE6编写. 我尝试了下面的代码,但它似乎完全被忽略了.为了测试它,我只需通过任务管理器向其发送“结束任务”. 我需要的是一种方法,让我的应用程序完成它在用户关闭应用程序时所执行的
我试图阻止我的应用程序被 Windows关闭.
该应用程序在Windows 8上运行并以XE6编写.
我尝试了下面的代码,但它似乎完全被忽略了.为了测试它,我只需通过任务管理器向其发送“结束任务”.
我需要的是一种方法,让我的应用程序完成它在用户关闭应用程序时所执行的操作,由Windows关闭的任务管理器完成.
正常关闭不是问题,这由FormCloseQuery事件处理.但其他两种方法我都无法工作.直到windows XP,通过捕获wm_endsession和wm_queryendsession很容易,从vista开始你需要使用ShutDownBlockReasonCreate,它返回true但似乎无论如何都不起作用.

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并删除睡眠不会改变任何内容.

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;

解决方法

根据 documentation阻止关闭,你需要返回FALSE以响应WM_QUERYENDSESSION.

更重要的是,你不能在这个消息处理程序中工作.这项工作必须在别处进行.如果您未及时回复此消息,系统将不会等待您.

>在开始工作之前调用ShutdownBlockReasonCreate.
>工作时从WM_QUERYENDSESSION返回FALSE.处理此消息时请勿工作.马上回来.
>完成工作后,调用ShutdownBlockReasonDestroy.

WM_QUERYENDSESSION的处理程序如下所示:

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

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

如果你的工作阻止主线程,那你就麻烦了.主线程必须是响应式的,否则系统不会等你.将工作放在一个线程中往往是前进的方向.如果您的主窗口不可见,那么您将无法阻止关闭.详情如下:http://msdn.microsoft.com/en-us/library/ms700677.aspx

如果你被发送到WM_ENDSESSION,那就太晚了.系统正在下降.

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

这与关闭阻塞无关.测试关闭阻塞的方法是注销.如果用户坚持要求杀死您的流程,那么您无能为力. Sertac的答案详细介绍了这一点.

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读