0

I have a console Application. I want it to start a process and end when that process ends. If the user hits ctrl + c, I don't want the application to close. If I set UseShellExecute = false, then this does exactly what I would expect - Ctrl C is ignored.

But it seems that when UseShellExecute:true, the ctrl+c event propagates to the child process and shuts down the child process even if the parent cancels it.

I can't UseShellExecute:true because I want to trap the consoleoutput and consoleerror events.

How can I stop the ctrl+c event from reaching the child process when UseShellExecute:false?

public static int Main(string[] args)
{
    Console.CancelKeyPress += ConsoleOnCancelKeyPress;

        Process process = new Process()
        {
            StartInfo = new ProcessStartInfo()
            {
                FileName = filename,
                Arguments = args,
                UseShellExecute = false,
                RedirectStandardError = true,
                RedirectStandardOutput = true,
                RedirectStandardInput = true,
                CreateNoWindow = false,
            }
        };

        process.OutputDataReceived += process_OutputDataReceived;
        process.ErrorDataReceived += process_ErrorDataReceived;

        process.Start();

        process.BeginOutputReadLine();
        process.BeginErrorReadLine();

        process.WaitForExit();

        return -1;
}

private static void ConsoleOnCancelKeyPress(object sender, ConsoleCancelEventArgs consoleCancelEventArgs)
{
    consoleCancelEventArgs.Cancel = true;
}
Kenn
  • 2,379
  • 2
  • 29
  • 38

2 Answers2

1

I solved this problem with a cascading set of processes. Process 'A' starts up process 'B' using UseShellExecute=true. Process 'B' starts up process 'C' using UseShellExecute=false.

When Process 'A' receives Ctrl+C, it traps it for the period that I wanted. Then it passes it along to 'B' via process.CloseMainWindow().

Process 'B', can still read the console output of the process 'C' (which I am attempting to host and monitor) since UseShellExecute=false. The CloseMainWindow sent from 'A' goes directly to both 'B and 'C' and closes both processes.

I was very fortunate that my logic could be segmented so cleanly between processes. Otherwise, I think this blog post from Stephen Toub is a great starting point for the Keyboard trap that Dave suggested. I couldn't get it working in my x64 process though I have not ruled out user error. http://blogs.msdn.com/b/toub/archive/2006/05/03/589423.aspx

Kenn
  • 2,379
  • 2
  • 29
  • 38
  • Ah there is a small change to make in his code for x64 work. It is actually documented in the code he supplies. – Dave Gordon Aug 26 '13 at 07:32
0

Use a Keyboard hook to trap Ctrl-C within the Console This will override the action. Use this code to enable that functionality:

http://blogs.msdn.com/b/toub/archive/2006/05/03/589423.aspx

Dave Gordon
  • 1,815
  • 4
  • 30
  • 52
  • http://stackoverflow.com/questions/177856/how-do-i-trap-ctrl-c-in-a-c-sharp-console-app – Kyle Jul 16 '13 at 02:06
  • @Kyle - That is not the same question. You'll notice i'm using the CancelKeyPress event in the above code already. – Kenn Jul 16 '13 at 02:10
  • @Kyle - The issue is not 'how to obtain the event' but rather 'how to stop the event from propogating to a child process' – Kenn Jul 16 '13 at 03:13
  • @Kenn I see what you mean, and I'm afraid I don't know enough about how signals (if that's what they are in Windows) are handled. It's not very nice, but could you launch a detached process and obtain stdout/err from files? Eg: child.exe args > ./stdout.log 2> ./stderr.log – Kyle Jul 16 '13 at 03:32