进程挂起等待输入的命令,RedirectStandardInput为'true'

时间:2011-12-27 18:36:51

标签: c# input process cmd

在另一个问题中解释了一些问题后,我继续编写了一个模拟Windows命令提示符的应用程序。每个命令都由一个调用“CMD.exe / C [command]”的Process对象执行,并将其标准输出/错误重定向到Winform。

一切顺利但是当我执行某些命令时表单崩溃,例如“time”或“wmic”请求某些用户交互(RedirectStandardInput为TRUE)。如何解决此问题使光标等待输入(如经典提示)?

这是代码

        Process cmdProcess = new Process();
        cmdProcess.StartInfo.FileName = "CMD.exe";
        cmdProcess.StartInfo.Arguments = "/C " + command;
        cmdProcess.StartInfo.WorkingDirectory = this.workingDir;
        cmdProcess.StartInfo.CreateNoWindow = true;
        cmdProcess.StartInfo.UseShellExecute = false;
        cmdProcess.StartInfo.RedirectStandardOutput = true;
        cmdProcess.StartInfo.StandardOutputEncoding = Encoding.Default;
        cmdProcess.StartInfo.RedirectStandardError = true;
        cmdProcess.StartInfo.StandardErrorEncoding = Encoding.Default;
        //cmdProcess.StartInfo.RedirectStandardInput = true;

        cmdProcess.Start();
        StreamReader outputR = cmdProcess.StandardOutput;
        StreamReader errorR = cmdProcess.StandardError;
        //StreamWriter inputW = cmdProcess.StandardInput;

        string output = outputR.ReadToEnd();
        string error = errorR.ReadToEnd();

        if (output.Length > 0)
            this.textArea.AppendText(Environment.NewLine + output);
        else if (error.Length > 0)
            this.textArea.AppendErrorText(Environment.NewLine + error);

我评论了启用输入重定向的所有部分,现在输出,例如,“time”命令不会询问任何用户输入并立即返回。显然我不喜欢这种行为;)

C:\Users\Alessandro\Progetti\CMDProject\CMDProject\bin\Debug>time
Ora corrente: 19:32:17,55
Immettere nuova ora:
C:\Users\Alessandro\Progetti\CMDProject\CMDProject\bin\Debug>

1 个答案:

答案 0 :(得分:1)

我过去做了类似的事情,看看我的代码,它看起来不像你设置了callbascks,尝试这个,将我的命令变成你想要的,希望这会有所帮助:如果你开始另一个线程确保第一个是关闭的,正如我的代码所示......

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;

using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;
using System.Globalization;

namespace VSSWriterTest
{
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }


    public class VSSCommands
    {
        public string VSS_VSSExecutable = "vssadmin";
        public string VSS_VSSListWriters = " list writers";
    }


    private void Form1_Load(object sender, EventArgs e)
    {
        //close handler
        this.FormClosing+=new FormClosingEventHandler(Form1_FormClosing);

    }

    private void Form1_FormClosing(object sender, EventArgs e)
    {

    }

    //my thread and process vars
    private Process m_Process;
    private Thread m_OutputThread;
    private Thread m_ErrorThread;
    private string m_TextToAdd;

   //basic writer command line stuff
    public class WriterStats
    {
        public string WriterName = "Writer Name";
        public string WriterTD = "Writer Id";
        public string WriterInstanceId = "Writer Instance Id";
        public string WriterState = "State";
        public string WriterLastError = "Last error";
        public string NoError = "No error";
    }



    private void StartVSSDiagnostics()
    {
        try
        {
            this.rtbVSSList.Clear();
            iErrorCount = 0;
            iWriterCount = 0;
            this.txtErrors.Clear();

            //start cmd prompt, then write command statement to console screen
            if ((StartVSSDiagnosticsThreads()))
            {
                VSSCommands ServiceCall = new VSSCommands();

                string msg = ServiceCall.VSS_VSSExecutable + ServiceCall.VSS_VSSListWriters;
                VSSStreamInput(msg);
            }

        }
        catch (Exception ex)
        {
           MessageBox.Show(ex.Message, "EVAS Backup and Restore");
        }
    }

    private void VSSStreamInput(string Text)
    {
        try
        {
            if (Text != string.Empty)
            {
                m_Process.StandardInput.WriteLine(Text);
                m_Process.StandardInput.Flush();
            }

        }
        catch (Exception ex)
        {
        }
    }

    private bool StartVSSDiagnosticsThreads()
    {

        try
        {
            //close threads if open
            CloseThreads();

            //start new cmd prompt thread
            m_Process = new Process();
            {
                m_Process.StartInfo.FileName = "cmd";
                m_Process.StartInfo.UseShellExecute = false;
                m_Process.StartInfo.CreateNoWindow = true;
                m_Process.StartInfo.RedirectStandardOutput = true;
                m_Process.StartInfo.RedirectStandardError = true;
                m_Process.StartInfo.RedirectStandardInput = true;

            }
            m_Process.Start();

            //create the call backs
            m_OutputThread = new Thread(StreamOutput);
            m_OutputThread.IsBackground = true;
            m_OutputThread.Start();
            m_ErrorThread = new Thread(StreamError);
            m_ErrorThread.IsBackground = true;
            m_ErrorThread.Start();

            return true;
        }
        catch (Exception ex)
        {
            return false;
        }
    }

    //this stream is feedback from the command prompt, its a delegate thats on a seperate thread other than this UI
    private void StreamOutput()
    {
        try
        {
            string Line = m_Process.StandardOutput.ReadLine();

            while (Line.Length >= 0)
            {
                if (Line.Length > 0)
                {
                    ConsoleMessage(ConvertFromOem(Line));
                }
                Line = m_Process.StandardOutput.ReadLine();
            }
        }
        catch
        {
            //ConsoleMessage(String.Format("""{0}"" Error!", m_Process.StartInfo.FileName))
        }
    }


    //convert text encoding to readable characters
    private string ConvertFromOem(string Text)
    {
        try
        {
            return Encoding.GetEncoding(CultureInfo.InstalledUICulture.TextInfo.OEMCodePage).GetString(Encoding.Default.GetBytes(Text));
        }
        catch (Exception ex)
        {
            return string.Empty;
        }
    }

    //stream error callback
    private void StreamError()
    {
        try
        {
            string Line = m_Process.StandardError.ReadLine();

            while (Line.Length >= 0)
            {
                Line = m_Process.StandardError.ReadLine();
                if (Line.Length > 0)
                {
                    ConsoleMessage(Line, true);
                }
            }
        }
        catch
        {
            //ConsoleMessage(String.Format("""{0}"" Error!", m_Process.StartInfo.FileName))
        }
    }

    //actual delegate that invokes the main thread
    private void ConsoleMessage(string Text, bool err = false)
    {
        try
        {
            if (err)
            {
                m_TextToAdd = "ERROR: " + Text;
            }
            else
            {
                m_TextToAdd = Text;
            }

            this.Invoke((MethodInvoker)this.RaiseConsoleTextEvent);

        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }


    //raise  text event, new text arrived from console
    private void RaiseConsoleTextEvent()
    {
        try
        {
            VSSMessages(m_TextToAdd);

        }
        catch (Exception ex)
        {
        }
    }


    //my message filter, what i want displayed on my UI, i parse microsoft logo and garbage to display results only
    private int iErrorCount = 0;
    private int iWriterCount = 0;
    private void VSSMessages(string e)
    {
        WriterStats IWriter = new WriterStats();


        if ((e.ToUpper().Contains(IWriter.WriterInstanceId.ToUpper()) | e.ToUpper().Contains(IWriter.WriterLastError.ToUpper()) |
            e.ToUpper().Contains(IWriter.WriterName.ToUpper()) | e.ToUpper().Contains(IWriter.WriterState.ToUpper()) |
            e.ToUpper().Contains(IWriter.WriterTD.ToUpper())))
        {
            if ((e.ToUpper().Contains(IWriter.WriterName.ToUpper())))
            {
                iWriterCount += 1;
                this.rtbVSSList.AppendText("Writer (" + iWriterCount.ToString() + ") " + e + Environment.NewLine);
            }
            else
            {
                this.rtbVSSList.AppendText(e + Environment.NewLine);
            }

            if ((e.ToUpper().Contains(IWriter.WriterLastError)))
            {
                if ((e.ToUpper().Contains(IWriter.NoError)))
                {
                    iErrorCount += 1;
                    this.txtErrors.ForeColor = Color.Red;
                }
            }

            this.txtErrors.Text = iErrorCount.ToString() + " Errors found in " + iWriterCount.ToString() + " system writers.";

            if ((e.ToUpper().Contains(IWriter.WriterLastError.ToUpper())))
            {
                this.rtbVSSList.AppendText(Environment.NewLine);
            }

            Application.DoEvents();

        }


    }

    //close any open threads, dont want run away threads!
    private void CloseThreads()
    {
        try
        {
            if (((m_OutputThread != null)))
            {
                if ((m_OutputThread.IsAlive))
                {
                    m_OutputThread.Abort();
                }
            }

            if (((m_ErrorThread != null)))
            {
                if ((m_ErrorThread.IsAlive))
                {
                    m_ErrorThread.Abort();
                }
            }

        }
        catch (Exception ex)
        {
        }
    }

    private void btnRun_Click(object sender, EventArgs e)
    {
        //begin
        StartVSSDiagnostics();
    }


}

}