C# RedirectStandardOutput from third party terminal stops at first character

275 Views Asked by At

I'm trying to redirect the output from a third party terminal (accoreconsole.exe). The output is redirected to a richtextbox.

If I manually type in the accoreconsole.exe from cmd I see the whole output but when I try to start it from my project it's stops at the first letter of the first row.

The first row where the output stops at letter R:

Redirect stdout (file: C:\Users\Marcus\AppData\Local\Temp\accc207883).

When I send something like "ipconfig" it work as it should. I tried to send the output to a .txt file and that worked. But when I tried to apply the text from the .txt file to my textbox it stops at the same letter (R). If I manually opend the .txt file and just save it I can apply it to the textbox.. Wierd?

Any ideas? :) Thanks!

Manually from cmd:

Microsoft Windows [Version 10.0.19043.1348]
(c) Microsoft Corporation. All rights reserved.

C:\Users\Marcus>"C:\Program Files\Autodesk\AutoCAD 2018\accoreconsole.exe"
Redirect stdout (file: C:\Users\Marcus\AppData\Local\Temp\accc207883).
AcCoreConsole: StdOutConsoleMode: processed-output: enabled,auto
AutoCAD Core Engine Console - Copyright 2017 Autodesk, Inc.  All rights reserved. (O.72.0.0)

Execution Path:
C:\Program Files\Autodesk\AutoCAD 2018\accoreconsole.exe

Version Number: O.72.0.0 (UNICODE)

Usage:
AcCoreConsole.exe [/i <input dwg>] /s <script>[/product <product>] [/l <language>] [/isolate <userid> <userDataFolder>] [/readonly] [/p[rofile] <profile>]

Example:
AcCoreConsole.exe /i 8th_floor.dwg /s test.scr /l en-US

C:\Users\Marcus>

Output from my project:

Microsoft Windows [Version 10.0.19043.1348]
(c) Microsoft Corporation. All rights reserved.

C:\Users\Marcus\source\repos\Test_Read_Console_Live\Test_Read_Console_Live\bin\Debug>"C:\Program Files\Autodesk\AutoCAD 2018\accoreconsole.exe"
R

My project code:

using System;
using System.Diagnostics;
using System.Windows.Forms;

namespace Test_Read_Console_Live
{
    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            run();

        }

        public void run()
        {
            Process cmd = new Process()
            {
                StartInfo = new ProcessStartInfo("cmd")
                {
                    RedirectStandardInput = true,
                    RedirectStandardOutput = true,
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    WindowStyle = ProcessWindowStyle.Hidden
                }
            };

            cmd.Start();
            cmd.StandardInput.WriteLine(@"""C:\Program Files\Autodesk\AutoCAD 2018\accoreconsole.exe""");

            cmd.StandardInput.Flush();
            cmd.StandardInput.Close();

            string output = cmd.StandardOutput.ReadToEnd();

            cmd.WaitForExit();
            cmd.Close();
            richTextBox1.Text = output;
        }
    }
}

2

There are 2 best solutions below

1
DRapp On

Here is a snippet of code I had for calling a DOS-based command terminal program.

Whatever the "exeToRun" program is, such as your AcCoreConsole.exe, and

                var info = new ProcessStartInfo();
                // call the DOS command, ensure the path to 
                // your exe file being called.
                info.FileName = Path.Combine(Environment.CurrentDirectory, exeToRun);
                info.Arguments = stringOfCommandArguments;
                info.RedirectStandardInput = true;
                info.UseShellExecute = false;
                info.RedirectStandardOutput = true;
                info.RedirectStandardError = true;
                // dont "SHOW" the black popup window in background making things look
                // like popup, popup, popup for each call going out to device.
                info.WindowStyle = ProcessWindowStyle.Hidden;
                // the "CreateNoWindow" actually prevents the black DOS window from showing.
                info.CreateNoWindow = true;
                p.StartInfo = info;
                p.Start();

                var sb = new StringBuilder();
                try
                {
                    while (!p.StandardOutput.EndOfStream)
                        sb.AppendLine(p.StandardOutput.ReadLine());

                    while (!p.StandardError.EndOfStream)
                        sb.AppendLine(p.StandardError.ReadLine());
                }
                catch
                {
                    sb.AppendLine("Error/Timeout getting results of request.");
                }

So, after the process.Start, I did a loop of capturing both standardOutput and standardError streams that are part of the process object. Hopefully this can get you over the hump you are working on.

Now, in the string builder, I can assess, write out and debug for later assessment. You can split into your own capture, but again, hopefully just the piece(s) you may be missing.

0
oli On

One can also use the dedicated event handlers to process the output and error streams asynchronously:

var startInfo = new ProcessStartInfo();
startInfo.FileName = "app.exe";
startInfo.UseShellExecute = false;
var p = new Process();
p.StartInfo = startInfo;

// Gather standard output in a string buffer
var outSb = new StringBuilder();
startInfo.RedirectStandardOutput = true;
p.OutputDataReceived += new DataReceivedEventHandler((sender, e) => { outSb.AppendLine(e.Data); });

// Gather standard error in a string buffer    
startInfo.RedirectStandardError = true;
var errSb = new StringBuilder();
p.ErrorDataReceived += new DataReceivedEventHandler((sender, e) => { errSb.AppendLine(e.Data); });
    
p.Start();
p.BeginOutputReadLine();
p.BeginErrorReadLine();
p.WaitForExit();

var allOutputLines = outSb.ToString();
var allErrorLines = errSb.ToString();