重定向的批处理文件进程输出未运行

时间:2015-06-18 11:44:15

标签: c# batch-file process console-application

我试图将批处理文件执行的输出重定向到控制台应用程序的主窗口。

我正在调用方法来运行这样的过程:

this.runProcess("\\bar\foo\blah\", "myBatch1.bat", "bat");

被调用的方法如下:

public void runProcess(string aPath,string aName,string aFiletype)
{

  Console.WriteLine();
  Console.WriteLine();
  Console.WriteLine("Started: {0}",DateTime.Now.ToString("dd-MMM hh:mm:ss"));
  Console.WriteLine("Will try run this file {0} {1}",aPath,aName);
  Console.WriteLine("File type {0}",aFiletype);

  string stInfoFileName;
  string stInfoArgs;

  if(aFiletype == "bat")
  {
    stInfoFileName = @"cmd.exe";
    stInfoArgs = "//c " + aName;
  }
  else
  { //vbs
    stInfoFileName = @"cscript";
    stInfoArgs = "//B " + aName;
  }

  this.aProcess.StartInfo.FileName = stInfoFileName;
  this.aProcess.StartInfo.Arguments =  stInfoArgs;
  this.aProcess.StartInfo.WorkingDirectory = @aPath;
  this.aProcess.StartInfo.CreateNoWindow = true;
  this.aProcess.StartInfo.UseShellExecute = false;
  this.aProcess.StartInfo.RedirectStandardError = true;
  this.aProcess.StartInfo.RedirectStandardOutput = true;

  this.aProcess.Start();
  Console.WriteLine("<<<got to here");

  Console.WriteLine(this.aProcess.StandardOutput.ReadToEnd());
  Console.WriteLine(this.aProcess.StandardError.ReadToEnd());

  this.aProcess.WaitForExit(); //<-- Optional if you want program running until your script exit
  this.aProcess.Close();

  Console.WriteLine("Finished: {0}",DateTime.Now.ToString("dd-MMM hh:mm:ss"));
}

为了弄清楚发生了什么,我已经为WriteLine添加了额外的电话 "<<<got to here"被写入控制台,然后它就会挂起而不再发生任何事情。

怀疑我的错误是非常微不足道的,因为我对这项技术的经验有限。

我做错了什么?

3 个答案:

答案 0 :(得分:2)

好吧,你正在使用ReadToEnd() - 这将会阻止,直到进程退出,基本上。

当您重定向标准输出和错误时,这是​​一个非常糟糕的主意 - 当I / O缓冲区变满时,两个应用程序都将冻结。

相反,您可能希望使用异步I / O来读取输出(并根据需要将其写入控制台 - 但您需要确保错误和输出不会相互混淆)。或者只是重定向其中一个而不是两个。

处理此问题的最简单方法是使用ErrorDataReceivedOutputDataReceived事件:

aProcess.ErrorDataReceived += (s, e) => Console.WriteLine(e.Data);
aProcess.OutputDataReceived += (s, e) => Console.WriteLine(e.Data);

aProcess.BeginOutputReadLine();
aProcess.BeginErrorReadLine();

aProcess.WaitForExit();

除了实际工作之外,这也意味着输出会在出现时打印出来,而不是在进程退出时打印出来。

答案 1 :(得分:1)

由于您希望在现有控制台中输出子项,因此您不需要任何重定向。只需将UseShellExecute设置为false,就不要设置CreateNoWindow

此代码适用于我:

using System;
using System.Diagnostics;

namespace ConsoleApplication1
{
    class Program
    {
        Process aProcess = new Process();

        public void runProcess(string aPath, string aName, string aFiletype)
        {
            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine("Started: {0}", DateTime.Now.ToString("dd-MMM hh:mm:ss"));
            Console.WriteLine("Will try run this file {0} {1}", aPath, aName);
            Console.WriteLine("File type {0}", aFiletype);

            string stInfoFileName;
            string stInfoArgs;

            if (aFiletype == "bat")
            {
                stInfoFileName = "cmd.exe";
                stInfoArgs = "/c " + aPath + aName;
            }
            else
            { //vbs
                stInfoFileName = "cscript";
                stInfoArgs = "/B " + aPath + aName;
            }

            this.aProcess.StartInfo.FileName = stInfoFileName;
            this.aProcess.StartInfo.Arguments = stInfoArgs;
            this.aProcess.StartInfo.WorkingDirectory = aPath;
            this.aProcess.StartInfo.UseShellExecute = false;

            this.aProcess.Start();

            Console.WriteLine("<<<got to here");

            this.aProcess.WaitForExit(); //<-- Optional if you want program running until your script exit
            this.aProcess.Close();

            Console.WriteLine("Finished: {0}", DateTime.Now.ToString("dd-MMM hh:mm:ss"));
        }

        static void Main(string[] args)
        {
            new Program().runProcess("c:\\working\\", "test.bat", "bat");
            Console.WriteLine("Exiting");
        }
    }
}

我取出了重定向和相关逻辑,以及设置CreateNoWindow的行。我还在命令行中添加了aPath,以便它可以用于UNC路径(没有驱动器号的路径),因为它们不能设置为工作目录。

答案 2 :(得分:0)

我在if(aFiletype == "bat")之后修改了第一个选项,并且bat文件正常运行。

public void runProcess(string aPath,string aName,string aFiletype)
{
  aProcess = new Process();

  Console.WriteLine();
  Console.WriteLine();
  Console.WriteLine("Started: {0}",DateTime.Now.ToString("dd-MMM hh:mm:ss"));
  Console.WriteLine("Will try run this file {0} {1}",aPath,aName);
  Console.WriteLine("File type {0}",aFiletype);

  string stInfoFileName;
  string stInfoArgs;

  if(aFiletype == "bat")
  {
    stInfoFileName = (@aPath + @aName);
    stInfoArgs = string.Empty;
  }
  else
  { //vbs
    stInfoFileName = @"cscript";
    stInfoArgs = "//B " + aName;
  }

  this.aProcess.StartInfo.FileName = stInfoFileName;
  this.aProcess.StartInfo.Arguments =  stInfoArgs;

  this.aProcess.StartInfo.WorkingDirectory = @aPath;

  //new 18 june 2015//////
  if(aFiletype == "bat")
  {
    this.aProcess.StartInfo.CreateNoWindow = true;
    this.aProcess.StartInfo.UseShellExecute = false;
    this.aProcess.StartInfo.RedirectStandardError = true;     //<< HJ
    this.aProcess.StartInfo.RedirectStandardOutput = true;    //<< HJ
  }
  ////////////////////////

  this.aProcess.StartInfo.WindowStyle = ProcessWindowStyle.Normal; //.Hidden
  this.aProcess.Start();

  aProcessName = this.aProcess.ProcessName;
  if(aFiletype == "bat")
  {
    this.aProcess.ErrorDataReceived += (s,e) => Console.WriteLine(e.Data);
    this.aProcess.OutputDataReceived += (s,e) => Console.WriteLine(e.Data);
    this.aProcess.BeginOutputReadLine();
    this.aProcess.BeginErrorReadLine();
  }

  this.aProcess.WaitForExit();
  this.aProcess.Dispose();

Console.WriteLine("Process {0} closed: {1}", this.aProcessName, DateTime.Now.ToString("dd-MMM hh:mm:ss"));
}
相关问题