Alexandr Sulimov
Alexandr Sulimov

Reputation: 1924

Redirect console output (not all data redirected C#)

If use default redirect from console

proc = new System.Diagnostics.Process();                    
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardInput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;

proc.OutputDataReceived += proc_OutputDataReceived;
proc.Exited += proc_Exited;
proc.ErrorDataReceived += proc_ErrorDataReceived;
proc.Start();
proc.BeginOutputReadLine();
proc.BeginErrorReadLine();

There are problems (tested on Windows Git bash msysgit)

  1. In OutputDataReceived come not all data.

  2. In OutputDataReceived not come data of text color.

  3. In ErrorDataReceived come wrong data.

Screen shots:

git bash console

git bash console

redirected data

redirected data

The questions:

  1. There are way get correct data by redirection?

  2. There are another way to get correct data from console?

Upvotes: 0

Views: 842

Answers (2)

Alexandr Sulimov
Alexandr Sulimov

Reputation: 1924

I am not found correct redirection console input and output.

My solution for task:

  1. Run console application.

    Process proc = new System.Diagnostics.Process();
    proc.StartInfo.FileName = "cmd.exe";
    proc.StartInfo.Arguments = "";
    proc.StartInfo.WorkingDirectory = "";
    proc.StartInfo.UseShellExecute = true;
    proc.StartInfo.CreateNoWindow = false;
    
    proc.Start();
    
    int count = 0;
    //wait console
    while (proc.MainWindowHandle == IntPtr.Zero)
    {
        Thread.Sleep(50);
        count++;
        if (count == 50)
            return;
    }
    
  2. Allow copy-paste from to console.

    //Attach to console
    DllImport.ConsoleFunctions.AttachConsole(proc.Id);
    //Get console output handle
    IntPtr cHandleO = DllImport.GetStdHandle(-11);
    //Set Quick edit Mode mode
    DllImport.SetConsoleMode(cHandleO, 0x0040);
    //Deattach from console
    DllImport.FreeConsole();
    
  3. View console output on Form.

    //Set my Panle as console window parent 
    DllImport.SetParent(proc.MainWindowHandle, panelConsole.Handle);
    DllImport.SendMessage(proc.MainWindowHandle, 0x0112, 0xF030, 0);
    //Resize
    DllImport.SetWindowPos(proc.MainWindowHandle, IntPtr.Zero, 0, 0, panelConsole.Width,     
        panelConsole.Height, 0x0040);
    //Hide border and title
    DllImport.SetWindowLong(proc.MainWindowHandle, -16, 0x10000000 | 0x00200000);
    
  4. Send command from TextBox to console.

    private DllImport.INPUT_RECORD[] PrepareData(string data)
    {
        DllImport.INPUT_RECORD[] rec = new DllImport.INPUT_RECORD[data.Length + 1];
        for (int i = 0; i < data.Length; i++)
        {
            rec[i].EventType = 0x0001;
            rec[i].KeyEvent = new DllImport.KEY_EVENT_RECORD();
            rec[i].KeyEvent.bKeyDown = true;
            rec[i].KeyEvent.dwControlKeyState = 0;
            rec[i].KeyEvent.UnicodeChar = data[i];
            rec[i].KeyEvent.wRepeatCount = 1;
            rec[i].KeyEvent.wVirtualKeyCode = data[i];
            rec[i].KeyEvent.wVirtualScanCode = (ushort) DllImport.MapVirtualKey(data[i], 0);
        }
        rec[data.Length].EventType = 0x0001;
        rec[data.Length].KeyEvent = new DllImport.KEY_EVENT_RECORD();
        rec[data.Length].KeyEvent.bKeyDown = true;
        rec[data.Length].KeyEvent.dwControlKeyState = 0;
        rec[data.Length].KeyEvent.UnicodeChar = '\n';
        rec[data.Length].KeyEvent.wRepeatCount = 1;
        rec[data.Length].KeyEvent.wVirtualKeyCode = '\n';
        rec[data.Length].KeyEvent.wVirtualScanCode = (ushort) DllImport.MapVirtualKey(0x0D, 0);
    
        return rec;
    }
    
    uint count = 0;
    //Fttach to console
    DllImport.AttachConsole(proc.Id);
    //Get input handle
    IntPtr cHandleI = DllImport.GetStdHandle(-10);
    //Prepare data
    DllImport.INPUT_RECORD[] data = PrepareData(tb.Text);
    //Write to console
    DllImport.WriteConsoleInput(cHandleI, data, data.Length, out count);
    //Deattach
    DllImport.FreeConsole();
    

Use PInvoke.net for some functions

Sample project

Upvotes: 2

God Dices
God Dices

Reputation: 51

StreamWriter input; Process p = new Process(); private void Form1_Load(object sender, EventArgs e) {

        p = new Process();
        p.StartInfo.FileName = ConfigurationManager.AppSettings["exe"];
        p.StartInfo.UseShellExecute = false;//自定义shell
        p.StartInfo.CreateNoWindow = true;//避免显示原始窗口
        p.StartInfo.RedirectStandardInput = true;//重定向标准输入(原来是CON)
        p.StartInfo.RedirectStandardOutput = true;//重定向标准输出
        p.StartInfo.RedirectStandardError = true;//重定向错误输出流
        p.OutputDataReceived += new DataReceivedEventHandler(Process_OutputDataReceived);
        p.ErrorDataReceived += new DataReceivedEventHandler(Process_OutputDataReceived);

        try
        {
            p.Start();//GO
            input = p.StandardInput;//重定向输入
            p.BeginOutputReadLine();//开始监控输出(异步读取)
        }
        catch (Win32Exception ) {
            MessageBox.Show("指定的可执行文件无效");
            Close();
        }

    }

Upvotes: 0

Related Questions