我正在制作一个应用程序,其中我想在系统关闭之前执行一些数据库查询。我正在使用此代码-
static void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e)
{
e.Cancel = true;
MessageBox.Show("Shut down canceled");
}
我确实执行了此应用程序并尝试关闭系统,并且此代码也捕获了关闭事件,但问题是在显示消息框后它也显示了此屏幕-[我无法发布图像,因为我没有10点]。
它显示了停止系统以使其关闭的应用程序的名称,并且还提供了“强制关闭按钮”,我不希望显示此屏幕,因为用户可以在执行查询之前强制关闭系统。
在这方面需要专家的建议,非常感谢。
最佳答案
简短可靠的答案:
在任何最新的Windows版本上,您都可以尝试取消关闭,但Windows可能会决定忽略您。这是设计使然。如果您绝对必须在终止进程之前完成操作,则正确的位置是SessionEnded处理程序。如果您有必须在流程终止前完成的任务,则在完成所有工作(因此查询等已完成)之前,不得从SessionEnded处理程序返回。
因此,除了处理SessionEnding(而不是(如果您愿意的话)),还应该处理SessionEnded并在其中工作:
static void SystemEvents_SessionEnded(object sender, SessionEndedEventArgs e)
{
WaitForQueriesToFinishOrSaveState(); // new code
}
如何实现等待将取决于您的应用程序;如果您需要重新运行查询,则可以在其中执行查询,或者您需要Thread.Join()或以其他方式等待后台任务完成;但它必须是阻塞等待(因此您无需在完成后才从函数返回)。
由于您不能绝对停止关机,因此在这种情况下尝试取消可能没有什么意义,所以我建议完全不要在SessionEnding中设置e.Cancel。在较旧的Windows版本上,这更有意义,但不幸的是现在意义不大了。
the API docs还建议不要在SessionEnding中做任何重要的工作(包括消息框),而是设置所有需要立即返回然后在SessionEnded中进行工作的标志。 (撇开证明:我怀疑如果您返回的速度不够快,这可能会加快用户“程序行为异常,是否要杀死它们”屏幕的出现,因为Windows认为您没有在玩很好。)
幕后花絮:
设置e.Cancel向Windows表示您希望会话不结束;但用户仍然可以浏览; Windows可能会出于任何相关原因决定忽略您的请求。这就是cookie崩溃的方式。您可能会发现黑客可以在特定情况下工作,但是没有经过Microsoft认可的API或方法,因此很可能在现在和将来都可以正常工作。
在幕后,Windows会向您的进程的Windows发送WM_QUERYENDSESSION消息,.NET会为您发送该消息,并将其转换为SessionEnding事件),并将您的取消(或取消)回传给Windows;如果不取消则返回TRUE,否则返回FALSE。
此后,Windows会查看所有进程的请求,并且根据关闭原因以及其他因素,尽管提出了此类请求,但很可能仍会决定继续进行。它还可以警告用户进程是否不合作,并为他们提供终止进程的选项。
无论是否处理WM_QUERYENDSESSION(SessionEnding),总是有最后一次清理的机会:您将收到WM_ENDSESSION消息(转换为SessionEnded)。棘手的是,您必须在所有SessionEnded处理程序返回之前完成所有重要任务!
Windows听到其WM_ENDSESSION(SessionEnded)调用的回音后,就您应用程序的生命周期而言,所有赌注都将关闭,Windows可以随时终止您的进程。
雷蒙德·陈(Raymond Chen)相当专业且最近才报道了这一点。
http://blogs.msdn.com/b/oldnewthing/archive/2013/06/27/10429232.aspx
作为一个脚注,SystemEvents.SessionEnded是一种便利;如果您有顶层应用程序窗口,则可以完全绕开它,并通过以下方法实现相同目的:
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x16) // WM_ENDSESSION
{
WaitForQueriesToFinishOrSaveState();
m.Result = IntPtr.Zero;
return;
}
base.WndProc(ref m);
}
关于c# - 如何取消电脑关机事件?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17389162/