【问题标题】:In C# How do you read from DOS program you executed if the program is constantly outputting?在 C# 中,如果程序不断输出,您如何从执行的 DOS 程序中读取?
【发布时间】:2014-03-03 15:54:02
【问题描述】:

我找到了很多关于如何执行 cmd.exe 和执行命令,甚至执行 nslookup 和交互的编码示例,但我遇到的问题是一个特定的 dos 程序,当它启动时,它不会停止“输出”。这是一些代码,我将发表评论以及我从 C# 得到的错误

这是我如何以更高级的方式设置它,以便我可以接收来自程序的事件输出

public void StartApplication(string appNameAndPath)
{
        StreamReader outputStream;
        Process p = new Process();
        p.StartInfo.FileName = appNameAndPath;
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.UseShellExecute = false;
        p.StartInfo.CreateNoWindow = false;//for now just so I can see it
        p.Start();
//here is my advanced example
if(advanced == true)
{
        outputStream = p.StandardOutput;
        DoReadOutPut();
}
else
{//here is a simple example 
    while (p.StandardOutput.ReadLine() != null)  //this hangs here until the application exists
    {
        txt += (p.StandardOutput.ReadLine());
    }
}
}

 void DoReadOutput()
 {
        outputStream.BaseStream.BeginRead( readOutputBuffer, 0, readOutputBuffer.Length, new AsyncCallback( OnReadOutputCompleted ), null );  
       //this does sometimes fire but only with 0 bytes, on other dos programs it would say Memory read not allowed
 }

 void OnReadOutputCompleted( IAsyncResult result )
 {
        int cbRead = outputStream.BaseStream.EndRead( result );
        ProcessOutput( readOutputBuffer, cbRead );
        DoReadOutput();
 }

 private void ProcessOutput(byte[] buffer, int cbRead)
 {
        string text = p.StartInfo.StandardOutputEncoding.GetString(buffer, 0, 10000); //this is where it hangs until the program exits or is not writing anymore
        this.Invoke((Action)delegate
        {

            SetTextBoxValue(text);//im doing this because im on another thread otherwise textBox1.Text - text"

        });
  }

我不想使用 API 和 GetText 并为 ReadLastLine 创建一个引擎,有人可以帮我吗?我想你会想要一个示例 exe,创建一个 while(true){Console.WriteLine("bla");} 足以作为示例 exe 而不是我遇到问题的 exe 的 C# 应用程序。 exe接管dos窗口并具有“老派界面”

【问题讨论】:

  • 您是否尝试过使用Process.OutputDataReceived 事件? msdn.microsoft.com/en-us/library/…
  • 我会快速尝试一下
  • Diamondo25 我试过了,程序继续运行,当我在调试时点击暂停时,它转到 sortProcess.WaitForExit(); 之后的行。并且从未进入 SortOutputHandler 事件
  • 你确定程序输出到stdout,而不是stderr?
  • 不知道出处,幸好他们有一个允许输出的参数

标签: c# multithreading cmd


【解决方案1】:

async/await 可以在这里提供帮助....

await Exec(yourExe,parameters);

Task Exec(string exe,string args)
{
    var tcs = new TaskCompletionSource<object>();

    ProcessStartInfo psi = new ProcessStartInfo();
    psi.FileName = exe;
    psi.UseShellExecute = false;
    psi.RedirectStandardOutput = true;
    psi.Arguments = args;

    var proc = Process.Start(psi);

    proc.OutputDataReceived += (s, e) =>
    {
        this.Invoke((Action) (()=>richTextBox1.AppendText(e.Data + Environment.NewLine)));
    };

    proc.Exited += (s, e) => tcs.SetResult(null);

    proc.EnableRaisingEvents = true;
    proc.BeginOutputReadLine();

    return tcs.Task;
}

【讨论】:

  • 先生现在试试这个
  • 这在上面有效,只有当我在 DOS 应用程序上选择按控制 z 或 C 或取消时,输出才会转到文本框。感谢您的尝试
  • 查看OutputDataReceived中的代码。它写信给richTextBox1。您可以使用 console.Write 更改它。
  • 所以你是说我应该创建另一个不是 winforms 的项目类型并改用 console.write 吗?
  • 我发现该应用程序有一个允许输出的 arg,所以它必须明确不输出谢谢!
【解决方案2】:

你需要处理回调事件来读取流:

  startInfo.UseShellExecute        = false;
  startInfo.CreateNoWindow         = true;
  startInfo.RedirectStandardOutput = true;
  startInfo.RedirectStandardError  = true;

  Process proc = new Process();
  proc.StartInfo           = startInfo;
  proc.ErrorDataReceived  += new DataReceivedEventHandler(DataReceiveHandler);
  proc.OutputDataReceived += new DataReceivedEventHandler(DataReceiveHandler);
  proc.Start();
  proc.BeginErrorReadLine();
  proc.BeginOutputReadLine();
  proc.WaitForExit();

【讨论】:

  • 其实我想我以前试过这个,但会试一试
  • 他们上面帖子中的一个问题是没有流,我会看看借来的代码
  • 这不起作用,因为我的进程从不退出或停止输入。与通常的如何与基于 cmd 或 dos 的程序交互相比,它在整篇文章中的主要转折点 =///
  • 如果您的进程永远不会退出(奇怪的是,b/c 在某些时候系统至少会关闭,或者服务可能会被用户停止),那么只需删除 WaitForExit() 调用,您的程序就会继续运行。
猜你喜欢
  • 2014-11-01
  • 1970-01-01
  • 2010-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多