4

I wanna redirect cmd.exe output somewhere, below code works when the command is a line:

Process p = new Process()
{
    StartInfo = new ProcessStartInfo("cmd")
    {
       UseShellExecute = false,
       RedirectStandardInput = true,
       RedirectStandardOutput = true,
       CreateNoWindow = true,
       Arguments = String.Format("/c \"{0}\"", command),
    }
};
p.OutputDataReceived += (s, e) => Messagebox.Show(e.Data);
p.Start();
p.BeginOutputReadLine();
p.WaitForExit();

But how about a series commands like WriteLine():

p.StandardInput.WriteLine("cd...");
p.StandardInput.WriteLine("dir");

how to get output in this situation?

3
  • clarify: do you want all outputs of your commands? or just the last one? Calling RunWithRedirect() consecutively already achieves your goal. Commented Apr 8, 2013 at 2:54
  • while, my commands are in series. Sth like "cd path" and then "do sth", i want all the outputs Commented Apr 8, 2013 at 3:01
  • 1
    how about Calling RunWithRedirect() consecutively ? sounds no problem in your case. Commented Apr 8, 2013 at 3:12

1 Answer 1

4

To achieve such behavior you should use /k switch to run cmd.exe in interactive mode.

The problem is to separate inputs from different commands. To do this you could change the standard prompt using prompt command:

prompt --Prompt_C2BCE8F8E2C24403A71CA4B7F7521F5B_F659E9F3F8574A72BE92206596C423D5 

So now it is pretty easy to determine the end of command output.

Here is the complete code:

public static IEnumerable<string> RunCommands(params string[] commands) {
    var process = new Process {
        StartInfo = new ProcessStartInfo("cmd") {
            UseShellExecute = false,
            RedirectStandardInput = true,
            RedirectStandardOutput = true,
            CreateNoWindow = true,
            Arguments = "/k",
        }
    };

    process.Start();

    const string prompt = "--Prompt_C2BCE8F8E2C24403A71CA4B7F7521F5B_F659E9F3F8574A72BE92206596C423D5 ";

    // replacing standard prompt in order to determine end of command output
    process.StandardInput.WriteLine("prompt " + prompt);
    process.StandardInput.Flush();
    process.StandardOutput.ReadLine();
    process.StandardOutput.ReadLine();

    var result = new List<string>();

    try {
        var commandResult = new StringBuilder();

        foreach (var command in commands) {
            process.StandardInput.WriteLine(command);
            process.StandardInput.WriteLine();
            process.StandardInput.Flush();

            process.StandardOutput.ReadLine();

            while (true) {
                var line = process.StandardOutput.ReadLine();

                if (line == prompt) // end of command output
                    break;

                commandResult.AppendLine(line);
            }

            result.Add(commandResult.ToString());

            commandResult.Clear();

        }
    } finally {
        process.Kill();
    }

    return result;
}

It works well but it looks like one big hack.

I'd recommend you to use process per command instead.

Sign up to request clarification or add additional context in comments.

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.