我们可以合作提出适用于control-c,control-break,注销,按下窗口X按钮等的东西吗?
这是我到目前为止所做的:
class Program
{
private static ConsoleEventHandlerDelegate consoleHandler;
delegate bool ConsoleEventHandlerDelegate(CtrlTypes eventCode);
static void Main(string[] args)
{
consoleHandler = new ConsoleEventHandlerDelegate(ConsoleCtrlCheck);
SetConsoleCtrlHandler(consoleHandler, true);
System.Diagnostics.Process.GetCurrentProcess().Exited
+= delegate(object sender, EventArgs e)
{
GeneralManager.Stop();
};
Console.CancelKeyPress += delegate(object sender,
ConsoleCancelEventArgs e)
{
e.Cancel = false;
GeneralManager.Stop();
};
GeneralManager.Start();
}
private static bool ConsoleCtrlCheck(CtrlTypes ctrlType)
{
switch (ctrlType)
{
case CtrlTypes.CTRL_C_EVENT:
Console.WriteLine("CTRL+C received!");
GeneralManager.Stop();
break;
case CtrlTypes.CTRL_BREAK_EVENT:
isclosing = true;
Console.WriteLine("CTRL+BREAK received!");
GeneralManager.Stop();
break;
case CtrlTypes.CTRL_CLOSE_EVENT:
Console.WriteLine("Program being closed!");
GeneralManager.Stop();
break;
case CtrlTypes.CTRL_LOGOFF_EVENT:
case CtrlTypes.CTRL_SHUTDOWN_EVENT:
Console.WriteLine("User is logging off!");
GeneralManager.Stop();
break;
}
return true;
}
#region unmanaged
[DllImport("kernel32.dll")]
static extern bool SetConsoleCtrlHandler(ConsoleEventHandlerDelegate
handlerProc, bool add);
public delegate bool HandlerRoutine(CtrlTypes CtrlType);
public enum CtrlTypes
{
CTRL_C_EVENT = 0,
CTRL_BREAK_EVENT,
CTRL_CLOSE_EVENT,
CTRL_LOGOFF_EVENT = 5,
CTRL_SHUTDOWN_EVENT
}
#endregion
}
两个问题:
在Managed Control-Break处理程序中,如果我们设置e.Cancel = true
,它会因.Net4的异常而失败。这在MSDN文章中有说明,没有解决方法:http://msdn.microsoft.com/en-us/library/system.consolecanceleventargs.cancel.aspx
我不知道如何取消ConsoleCtrlCheck
中的关闭。我得到一两次清理,但我宁愿取消并确保一切正常完成。
更新
感谢您的回复。两者都赞成。将等待,看看是否有人能够提出直接解决我要求的回复,否则将接受其中一个“使用NT服务”的答案。
答案 0 :(得分:0)
我花了几个小时看这个,因为我现在没有时间建立一个有效的代码;虽然它可能很短,但正确的做法需要一段时间。我只是给你链接到完成这项工作所需的各种东西:
总结粘贴代码中的经验教训:
需要一个消息泵来处理部分/全部WM_QUERYENDSESSION,WM_ENDSESSION,CTRL_SHUTDOWN_EVENT(在c#SystemEvents.SessionEnding中可能涵盖部分/全部)
获取消息泵的最简单方法是使其成为隐藏的表单/窗口应用程序,但我记得可以构建为控制台应用程序并添加消息泵。我没有在粘贴中包含该代码。
“如果应用程序必须阻止潜在的系统关闭,它可以调用ShutdownBlockReasonCreate函数”
由于AllocConsole用于创建控制台,您需要使用SetConsoleCtrlHandler并在处理程序中使用ExitThread(1)。这是一个“黑客”,可以杀死关闭控制台的线程。它在FarManager中使用。例如,参见interf.cpp
使用AllocConsole时,还需要初始化和清理控制台。
据报道按CTRL + C会搞砸输入。我不确定FarManager是否正在处理这种情况。 interf.cpp中的CTRL_BREAK_EVENT处理程序中有一些代码,我不确定它是做什么的。
FarManager还处理WM_POWERBROADCAST,可能与暂停
如果所有这些都不够(应该是),您还可以将控制台添加到另一个进程中并将您的消息IPC添加到此处,如此处所示。 Why does closing a console that was started with AllocConsole cause my whole application to exit? Can I change this behavior?
RMTool可用于模拟用于测试的注销/关闭消息:http://download.microsoft.com/download/d/2/5/d2522ce4-a441-459d-8302-be8f3321823c/LogoToolsv1.0.msi
MSDN在microsoft.win32.systemevents.sessionending.aspx上也有一些C#代码 和microsoft.win32.systemevents.aspx(隐藏形式示例)mischel.com/pubs/consoledotnet/consoledotnet.zip有一个示例winTest项目,正在使用AllocConsole并处理了一些事件。