这不是此post的副本。我从这篇文章中得到了我的解决方案,但它不起作用,更不用说我的应用程序是一个winforms应用程序,而不是一个控制台应用程序。
所以我有一个在后台运行的项目。基本上,我创建了一个Windows窗体应用程序,但我没有在Program.cs中调用Form。我创建了一个监听应用程序退出时间的类:
class ShutDownManager
{
public ShutDownManager()
{
_handler += new EventHandler(Handler);
SetConsoleCtrlHandler(_handler, true);
}
static bool exitSystem = false;
[DllImport("Kernel32")]
private static extern bool SetConsoleCtrlHandler(EventHandler handler, bool add);
private delegate bool EventHandler(CtrlType sig);
static EventHandler _handler;
enum CtrlType
{
CTRL_C_EVENT = 0,
CTRL_BREAK_EVENT = 1,
CTRL_CLOSE_EVENT = 2,
CTRL_LOGOFF_EVENT = 5,
CTRL_SHUTDOWN_EVENT = 6
}
private static bool Handler(CtrlType sig)
{
Console.Writeline("I'M OUT OF HERE");
return true;
}
}
我在Program.cs的Main函数中创建了这个类的实例。 然而,这似乎并没有激发。它在控制台应用程序中的功能就像一个魅力,但当涉及到我的表单应用程序(没有表单)时,它不起作用。 可能是什么问题?
我在Main的代码:
static void Main()
{
ShutDownManager sdm = new ShutDownManager();
StartUpManager.AddApplicationToCurrentUserStartup();
Timers timers = new Timers();
}
答案 0 :(得分:0)
让我打破你的情况:摘自docs.microsoft.com SetConsoleCtrlHandler
每个控制台进程都有自己的应用程序定义的HandlerRoutine函数列表,用于处理CTRL + C和CTRL + BREAK信号。处理程序函数还处理用户关闭控制台,注销或关闭系统时系统生成的信号。控制台进程通过调用SetConsoleCtrlHandler函数来添加或删除其他处理函数,该函数不会影响其他进程的处理函数列表。
正如您所注意到的,这似乎仅指控制台进程。当其他应用程序退出时,它无法告诉您,但仅限于此应用程序。此外,它还可以通知您LOGOFF
和SHUTDOWN
。此外,由于没有控制台(因为您需要后台进程),因此不涉及CTRL-C或CTRL-BREAK处理。
结论:最好的情况是,您只能收到有关LOGOFF
和SHUTDOWN
winforms app同一页面的相关信息:
此功能为控制台应用程序和服务提供了类似的通知, WM_QUERYENDSESSION为图形应用程序提供了消息泵。
您的代码有什么问题?
嗯,它旨在在系统运行应用程序时LOGOFF
或SHUTDOWN
时提供回调。不用说,您的申请已经退出接收此类活动。因此,您必须在注册回调后等待。
最好的方法是什么?
您应该为此编写服务。如果我没有弄错的话,服务已收到LOGOFF
和SHUTDOWN
的通知
How to write a simple C# service有一个很好的例子。
编辑:
为了更全面地理解,您可能需要查看MSDN docs about ServiceBase class。此外,您应该查看OnSessionChange
事件,该事件会通知all session events。它在SessionChangeDescription
class doc有一些有用的代码摘录。同样适用于OnShutdown
event
现在,如果您无法执行Windows服务,则必须从winform应用程序创建Form
并使表单不可见。然后,您应该处理WM_QUERYENDSESSION
event或使用SystemEvents.SessionEnding
Event来处理这种情况
该示例代码
var frm = new Form();
frm.Activated += (s, e) => { frm.Visible = false; };
SystemEvents.SessionEnded += (s, e) => { /* your code to handle logoff and shutdown */ };
Application.Run(frm);