2

I need to execute a shell command from c# code and then log to a file the output of the shell.

The code i use to execute the shell command is:

using (var process = Process.Start(new ProcessStartInfo
{
    FileName = fileName,
    Arguments = arguments,
    CreateNoWindow = false,
    WindowStyle = ProcessWindowStyle.Normal,
    RedirectStandardOutput = false,
    UseShellExecute = true,
}))
{
    // blocking wait for the process to end
    process.WaitForExit();
}

I read other answers that change RedirectStandardOutput = true and useShellExecute = false so they can get console output with

string output = process.StandardOutput.ReadToEnd();

But this won't open the shell window.

Is there a way to display the command output to the console window and get that output?

Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
S.Orioli
  • 443
  • 6
  • 21
  • Just look on this:https://stackoverflow.com/questions/39358017/plink-returning-unwanted-characters-via-c-sharp it helped me in the past. – Grigoris Loukidis May 24 '19 at 14:42
  • Did the process run? Did you get the output? You redirected the output to a file, so it won't appear in any window. It's the same as writing `dir > list.txt`. You won't see the output, it will all go to the file – Panagiotis Kanavos May 24 '19 at 14:53
  • BTW that's explained in [RedirectStandardOutput](https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.processstartinfo.redirectstandardoutput?view=netframework-4.8) `By setting RedirectStandardOutput to true to redirect the StandardOutput stream, you can manipulate or suppress the output of a process. For example, you can filter the text, format it differently, or write the output to both the console and a designated log file.` – Panagiotis Kanavos May 24 '19 at 14:56
  • See whether this help: [How do I get output from a command to appear in a control on a Form in real-time?](https://stackoverflow.com/a/51682585/7444103). There's also a sample project you can download and use for testing. – Jimi May 24 '19 at 14:58
  • 1
    I don't want to redirect the standard output, but just take what the command printed on the console window. Just take whatever is on the console and put in a string. – S.Orioli May 24 '19 at 14:59
  • @S.Orioli that's no "just". You can't get that output without redirecting it. What you can do though is read it and then write it out to your console – Panagiotis Kanavos May 24 '19 at 15:01
  • What is printed in the Console is written to StandardOutput, that's why you redirect it, so you can read it. – Jimi May 24 '19 at 15:01
  • @S.Orioli if you read any of the articles about the new Windows Terminal or ConPTY etc, you;ll see that the console is managed by the OS, which in front of the application, takes whatever is written to the standard output and sends it to the terminal. To do what you want you'd have to interact with the OS to somehow clone whatever the OS sends to the terminal. Doing so will become easier *in the future*. – Panagiotis Kanavos May 24 '19 at 15:03
  • @S.Orioli in both Linux and Windows people use the [tee](https://en.wikipedia.org/wiki/Tee_(command)) command to read an application's standard output and write it out to both the console and a file – Panagiotis Kanavos May 24 '19 at 15:05

1 Answers1

2

Could use something like that

using System;
using System.Diagnostics;

    namespace InteractWithConsoleApp
    {
        class Program
        {
            static void Main(string[] args)
            {
                ProcessStartInfo cmdStartInfo = new ProcessStartInfo();
                cmdStartInfo.FileName = @"C:\Windows\System32\cmd.exe";
                cmdStartInfo.RedirectStandardOutput = true;
                cmdStartInfo.RedirectStandardError = true;
                cmdStartInfo.RedirectStandardInput = true;
                cmdStartInfo.UseShellExecute = false;
                cmdStartInfo.CreateNoWindow = true;

                Process cmdProcess = new Process();
                cmdProcess.StartInfo = cmdStartInfo;
                cmdProcess.ErrorDataReceived += cmd_Error;
                cmdProcess.OutputDataReceived += cmd_DataReceived;
                cmdProcess.EnableRaisingEvents = true;
                cmdProcess.Start();
                cmdProcess.BeginOutputReadLine();
                cmdProcess.BeginErrorReadLine();

                cmdProcess.StandardInput.WriteLine("ping google.com.ua");     //Execute ping google.com.ua
                cmdProcess.StandardInput.WriteLine("exit");                  //Execute exit.

                cmdProcess.WaitForExit();
            }

            static void cmd_DataReceived(object sender, DataReceivedEventArgs e)
            {
                Console.WriteLine("Output from other process");
                Console.WriteLine(e.Data);
            }

            static void cmd_Error(object sender, DataReceivedEventArgs e)
            {
                Console.WriteLine("Error from other process");
                Console.WriteLine(e.Data);
            }
        }
    }
Oleg Bondarenko
  • 1,694
  • 1
  • 16
  • 19
  • Basically this redirect the standard output, use the text and then print it to the console. With a little modification, it works perfectly. Thanks. – S.Orioli May 27 '19 at 09:09
  • But there is only 1 console window in this case; the parent program's console. What if therer are two child programs consoles we want to display? It will become very chaotic right? Could parent program have two console windows? – pete Feb 07 '22 at 08:29
  • @pete it is huge topic related to other question. Basically process can have only one associated console. But your application can has multiple processes and multiple consoles like there https://www.codeproject.com/Articles/13368/Multiple-consoles-for-a-single-application – Oleg Bondarenko Feb 07 '22 at 11:23