Reputation: 5444
I have created a console application which has a method that stores kinect stream to hard disk. I want to capture console exit event in order to close the kinect stream since I have issues when the console exit from close event. I want to find a way to detect the exit event of the console. I came across solutions like the following one. I add the following code to my app:
[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)
{
switch (sig)
{
case CtrlType.CTRL_C_EVENT:
case CtrlType.CTRL_LOGOFF_EVENT:
case CtrlType.CTRL_SHUTDOWN_EVENT:
case CtrlType.CTRL_CLOSE_EVENT:
default:
return false;
}
}
And in the main function:
Program obj = new Program(dirPath + args[3] + "_" + args[4]);
_handler += new EventHandler(Handler);
SetConsoleCtrlHandler(_handler, true);
Console.ReadLine();
I am wandering firstly if I can import handler event to a boolean variable and secondly how can I give it as an input to program constructor in order to close my stream.
EDIT: My program constructor:
public Program(string filePath)
{
Thread thread = new Thread(() => writeRGSStream(file));
thread.Start();
writeSkelFiles(file);
}
I want to give the flag input inside the writeRGSStream method. Can I call
SetConsoleCtrlHandler(new HandlerRoutine(ConsoleCtrlCheck), true);
inside that method in order to get the flag value?
Upvotes: 2
Views: 2087
Reputation: 294
Use the CancelKeyPress event (fired on CTRL+C).
Console.CancelKeyPress += Console_CancelKeyPress;
do things before close here
private static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
{
Process.GetCurrentProcess().CloseMainWindow();
}
Hopefully this is what you tried to do.
Upvotes: 1
Reputation: 941585
return false;
This does not do what you hope it does. You cannot cancel a close request, the return value merely tells Windows whether it should call any other registered handlers. So whether you return true or false has no affect on the outcome, the OS will always terminate the program.
So anything you need to do must be done inside the callback method. Beware that you have very limited options. After all, your main thread is busy writing that file, you cannot delete it. Nor is it a real fix at all, you still have trouble if your app terminates for any other reason. Like an unhandled exception, the user killing it with Task Manager or somebody tripping over the power cord and unplugging the machine.
Just write smarter code, create the file with a temporary name and rename the file after you are done writing it. Now you never care that your program gets interrupted for any reason.
Upvotes: 1
Reputation: 1333
Look at this example, it works fine:
Main
private static bool isclosing = false;
static void Main(string[] args)
{
SetConsoleCtrlHandler(new HandlerRoutine(ConsoleCtrlCheck), true);
Console.WriteLine("CTRL+C,CTRL+BREAK or suppress the application to exit");
while (!isclosing) ;
}
Console check
private static bool ConsoleCtrlCheck(CtrlTypes ctrlType)
{
// Put your own handler here
switch (ctrlType)
{
case CtrlTypes.CTRL_C_EVENT:
isclosing = true;
Console.WriteLine("CTRL+C received!");
break;
case CtrlTypes.CTRL_BREAK_EVENT:
isclosing = true;
Console.WriteLine("CTRL+BREAK received!");
break;
case CtrlTypes.CTRL_CLOSE_EVENT:
isclosing = true;
Console.WriteLine("Program being closed!");
break;
case CtrlTypes.CTRL_LOGOFF_EVENT:
case CtrlTypes.CTRL_SHUTDOWN_EVENT:
isclosing = true;
Console.WriteLine("User is logging off!");
break;
}
return true;
}
And WinAPI part:
#region unmanaged
// Declare the SetConsoleCtrlHandler function
// as external and receiving a delegate.
[DllImport("Kernel32")]
public static extern bool SetConsoleCtrlHandler(HandlerRoutine Handler, bool Add);
// A delegate type to be used as the handler routine
// for SetConsoleCtrlHandler.
public delegate bool HandlerRoutine(CtrlTypes CtrlType);
// An enumerated type for the control messages
// sent to the handler routine.
public enum CtrlTypes
{
CTRL_C_EVENT = 0,
CTRL_BREAK_EVENT,
CTRL_CLOSE_EVENT,
CTRL_LOGOFF_EVENT = 5,
CTRL_SHUTDOWN_EVENT
}
#endregion
Upvotes: 5