6

First of all, I've read all related topics and they gave general idea but implementation doesn't work for me:
Send strings from one console application to another
How to send input to the console as if the user is typing?
Sending input/getting output from a console application (C#/WinForms)
I have a console application that is doing some actions in background until cancellation is requested. Typical usage scenario is :
1) Execute application
2) Enter input data
3) Issue start command
4) After some time passes, enter stop command
5) Exit application
Child application Program.cs :

static void Main()
{
    Console.WriteLine("Enter input parameter : ");
    var inputParameter = Console.ReadLine();
    Console.WriteLine("Entered : " + inputParameter);

    var tokenSource = new CancellationTokenSource();
    var token = tokenSource.Token;
    Task.Factory.StartNew(() =>
        {
            while (true)
            {
                if (token.IsCancellationRequested)
                {
                    Console.WriteLine("Stopping actions");
                    return;
                }
                // Simulating some actions
                Console.Write("*");
            }
        }, token);
    if (Console.ReadKey().KeyChar == 'c')
    {
        tokenSource.Cancel();
        Console.WriteLine("Stop command");
    }
    Console.WriteLine("Finished");
    Console.ReadLine();
}

What I'm looking for is some sort of host utility to control this application - spawn multiple instances and perform required user actions on each instance. Host application Program.cs :

static void Main()
{
    const string exe = "Child.exe";
    var exePath = System.IO.Path.GetFullPath(exe);
    var startInfo = new ProcessStartInfo(exePath)
    {
        RedirectStandardOutput = true,
        RedirectStandardInput = true,
        WindowStyle = ProcessWindowStyle.Hidden,
        WindowStyle = ProcessWindowStyle.Maximized,
        CreateNoWindow = true,
        UseShellExecute = false
    };

    var childProcess = new Process { StartInfo = startInfo };
    childProcess.OutputDataReceived += readProcess_OutputDataReceived;
    childProcess.Start();
    childProcess.BeginOutputReadLine();
    Console.WriteLine("Waiting 5s for child process to start...");
    Thread.Sleep(5000);

    Console.WriteLine("Enter input");
    var msg = Console.ReadLine();
    // Sending input parameter
    childProcess.StandardInput.WriteLine(msg);
    // Sending start command aka any key
    childProcess.StandardInput.Write("s");
    // Wait 5s while child application is working
    Thread.Sleep(5000);
    // Issue stop command
    childProcess.StandardInput.Write("c");
    // Wait for child application to stop
    Thread.Sleep(20000);
    childProcess.WaitForExit();
    Console.WriteLine("Batch finished");    
    Console.ReadLine();
}

When I run this tool, after first input it crashes with "has stopped working" error and prompt to send memory dump to Microsoft. Output window in VS shows no exceptions.
Guess this problem occurs somewhere between applications and may be because of output stream buffer overflow (child app is writing a lot of stars each second which mimics real output which may be huge) and I yet have no idea how to fix it. I don't really need to pass child's output to host (only send start-stop commands to child), but commenting RedirectStandardOutput and OutputDataReceived doesn't fix this problem. Any ideas how to make this work?

6
  • Why not using IPC and Pipe? It is very easy if you want to work on a single client or inside a LAN. WCF is another option. Commented Sep 11, 2013 at 13:27
  • I need to literally pass 3 strings from one application to another. Trying to keep things as simple as possible. Commented Sep 11, 2013 at 13:29
  • There is in general not much point to starting many processes to get a job done. You'll accomplish the exact same thing by starting many threads. Many advantages, including getting much better diagnostics when something goes wrong. Commented Sep 11, 2013 at 13:31
  • Makes no difference what you want to communicate. Recommended Readings: msdn.microsoft.com/en-us/library/bb546085.aspx and stackoverflow.com/questions/13806153/example-of-named-pipes Commented Sep 11, 2013 at 13:32
  • @HansPassant Well, each child application issues around 1000 service requests (20 simultaneous on average) per minute and memory consumption is an issue (OutOfMemory). Not much room for optimization taking into account the fact standard WCF and SoapHttpClientProtocol wrappers are used. Commented Sep 11, 2013 at 13:42

3 Answers 3

10

I would recommend using NamedPipeServerStream and NamedPipeClientStream, which allows you to open a stream which will communicate between processes on a given machine.

First, this will create a pipe server stream and wait for someone to connect to it:

    var stream = new NamedPipeServerStream(this.PipeName, PipeDirection.InOut);
    stream.WaitForConnection();
    return stream;

Then, this will connect to that stream (from your other process), allowing you to read / write in either direction:

    var stream = new NamedPipeClientStream(".", this.PipeName, PipeDirection.InOut);
    stream.Connect(100);
    return stream;
Sign up to request clarification or add additional context in comments.

Comments

0

Another alternative is to use MSMQ, you can find a good tutorial here

Comments

0

I would advise to look to the Working with memory mapped files in .NET 4 http://blogs.msdn.com/b/salvapatuel/archive/2009/06/08/working-with-memory-mapped-files-in-net-4.aspx

It's fast and efficient.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.