如何使用SetConsoleHandler()来阻止出境电话
题
我知道,我必须使用setconsolehandler()
如果我要管理控制台关闭事件。
我不知道如何阻止CTRL_CLOSE_EVENT
。我试图返回false / true,如果能抓住这一事件,但没有成功。
下面是我到目前为止(谢谢你,安东Gogolev!)
[DllImport("Kernel32")]
public static extern bool SetConsoleCtrlHandler(HandlerRoutine Handler, 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
}
private static bool ConsoleCtrlCheck(CtrlTypes ctrlType)
{
if(ctrlType == CtrlTypes.CTRL_CLOSE_EVENT)
return false;// I have tried true and false and viceversa with the return
// true/false but I cant seem to get it right.
return true;
}
//and then I use this to call it
SetConsoleCtrlHandler(new HandlerRoutine(ConsoleCtrlCheck), true);
也就是它可以运行一个新的线程来监视控制台是否关闭和块关闭,如果主线程在做某件事的中间?
解决方案
有 SetConsoleCtrlHandler()
文档说:
在系统中,当用户关闭控制台,注销,或关闭该系统,以便该过程有机会终止之前清理产生CTRL_CLOSE_EVENT,CTRL_LOGOFF_EVENT,和CTRL_SHUTDOWN_EVENT信号。
这意味着处理CTRL + C或CTRL + BREAK事件时不同,你的进程没有得到机会,取消关闭,注销或关机。
其他提示
其实你可以阻止它(我至少转载此在Windows XP)。例如,如果在你的处理器,你有无限循环和睡眠,这会从永远终止阻止这一进程(或者至少很长一段时间,或直到用户通过任务管理器终止进程)。
如果你真的需要启动一个线程,你可以使用(在C#AutoResetEvent
)等待状态,并开始你的线程(尽管一个新的线程可能不需要在大多数情况下),然后通知等待状态时,你的线程完了。然而,仅仅在处理程序做任何清理就足以在大多数情况下。
如果在最坏的情况下,你也永远等待下去,该过程将保持运行,你就可以看到它时,你(至少在Windows XP)重新登录。然而,这会导致桌面才去注销屏幕(在等待您的应用程序了退出)暂停大约20秒钟,然后在注销屏幕(我猜当它试图得到第二次)再次暂停。当然,我强烈建议不要永远等待;对于任何长期运行的东西,你真的应该把这个服务。
我发现了一个可能的“黑客”,可以防止从封闭的应用,同时仍然服从整齐控制台关闭请求。 尤其是,这是合适的,我认为,对于已经创造了一个控制台的“额外”的GUI应用程序。 从MSDN文档,在其中处理程序Ctrl键被称为新线程的点强>在该过程中创建的调用处理程序。我的解决办法,那么,是杀死入侵的袭警线程之前的默认处理程序可以调用了ExitProcess。在处理程序例程(代码在C ++):
// Detach Console:
FreeConsole();
// Prevent closing:
ExitThread(0);
return TRUE; // Not reached
编辑:看来这确实会引起一些问题,如可以预期的,我想。到AllocConsole的后续调用()无限期挂起,所以我怀疑离开螺纹过早未能正确地进行清理。
修改2:强>
要上述澄清,我已发现没有直接问题同继续运行该程序。但请记住,我们已经强制终止该KERNEL32创造了一个线程,所以里面KERNEL32任何资源可能处于不确定状态。这可能导致不可预见的问题当程序继续运行。
大多数情况下,我认为,这些问题将关系到控制台API。就像提到,AllocConsole
无法从该点开始工作(它将应用程序挂起),所以程序无法打开一个新的控制台。这极有可能是其他控制台功能也将失败。基本上,任何你从该点起做以任何方式(直接或间接)调用到KERNEL32受不确定的行为,但我怀疑,在实践中也不会有的控制台功能之外的任何问题。
我的结论是,你应该避免这种方法,如果可能的话,但是如果过早终止更糟糕的是,那么这可以被认为是紧急情况下的变通,要谨慎,谨慎使用。