当前位置:  开发笔记 > 编程语言 > 正文

操作方法:在C#中执行命令行,获取STD OUT结果

如何解决《操作方法:在C#中执行命令行,获取STDOUT结果》经验,为你挑选了7个好方法。

如何从C#执行命令行程序并返回STD OUT结果.具体来说,我想对以编程方式选择的两个文件执行DIFF,并将结果写入文本框.是的,我可以为自己解决这个问题,但肯定有人做过类似的事情,我很懒...



1> 小智..:
// Start the child process.
 Process p = new Process();
 // Redirect the output stream of the child process.
 p.StartInfo.UseShellExecute = false;
 p.StartInfo.RedirectStandardOutput = true;
 p.StartInfo.FileName = "YOURBATCHFILE.bat";
 p.Start();
 // Do not wait for the child process to exit before
 // reading to the end of its redirected stream.
 // p.WaitForExit();
 // Read the output stream first and then wait.
 string output = p.StandardOutput.ReadToEnd();
 p.WaitForExit();

代码来自MSDN.


您可以通过`{YourProcessObject} .StartInfo.Arguments`字符串为您的调用添加参数.
有没有办法在没有批处理文件的情况下执行此操作?事实是,我需要向命令发送一些参数.我正在使用xsd.exe /type:,因此我需要能够设置Assembly和ClassName,然后运行该命令.
如何使进程以管理员身份运行?
来自c#编译器的快速抬头:Process对象必须将UseShellExecute属性设置为false才能重定向IO流.
我遇到了一些问题,我的进程使用这段代码完全停止,因为进程已经为`p.StandardError`流写入了足够的数据.当流变满时,似乎该过程将暂停,直到数据被消耗为止,因此我必须同时读取"StandardError"和"StandardOutput"以确保任务正确执行.
如果你喜欢执行和交互式应用怎么办?因为如果你这样做就不能使用ReadToEnd.

2> Jeremy..:

这是一个快速示例:

//Create process
System.Diagnostics.Process pProcess = new System.Diagnostics.Process();

//strCommand is path and file name of command to run
pProcess.StartInfo.FileName = strCommand;

//strCommandParameters are parameters to pass to program
pProcess.StartInfo.Arguments = strCommandParameters;

pProcess.StartInfo.UseShellExecute = false;

//Set output of program to be written to process output stream
pProcess.StartInfo.RedirectStandardOutput = true;   

//Optional
pProcess.StartInfo.WorkingDirectory = strWorkingDirectory;

//Start the process
pProcess.Start();

//Get program output
string strOutput = pProcess.StandardOutput.ReadToEnd();

//Wait for process to finish
pProcess.WaitForExit();


+1,用于显示如何向运行命令行程序添加参数(公认的答案没有此参数)。

3> 小智..:

还有一个我发现有用的参数,我用它来消除进程窗口

pProcess.StartInfo.CreateNoWindow = true;

这有助于完全隐藏黑色控制台窗口,如果这是你想要的.


救了我很多头痛.谢谢.

4> Lu55..:
// usage
const string ToolFileName = "example.exe";
string output = RunExternalExe(ToolFileName);

public string RunExternalExe(string filename, string arguments = null)
{
    var process = new Process();

    process.StartInfo.FileName = filename;
    if (!string.IsNullOrEmpty(arguments))
    {
        process.StartInfo.Arguments = arguments;
    }

    process.StartInfo.CreateNoWindow = true;
    process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
    process.StartInfo.UseShellExecute = false;

    process.StartInfo.RedirectStandardError = true;
    process.StartInfo.RedirectStandardOutput = true;
    var stdOutput = new StringBuilder();
    process.OutputDataReceived += (sender, args) => stdOutput.AppendLine(args.Data); // Use AppendLine rather than Append since args.Data is one line of output, not including the newline character.

    string stdError = null;
    try
    {
        process.Start();
        process.BeginOutputReadLine();
        stdError = process.StandardError.ReadToEnd();
        process.WaitForExit();
    }
    catch (Exception e)
    {
        throw new Exception("OS error while executing " + Format(filename, arguments)+ ": " + e.Message, e);
    }

    if (process.ExitCode == 0)
    {
        return stdOutput.ToString();
    }
    else
    {
        var message = new StringBuilder();

        if (!string.IsNullOrEmpty(stdError))
        {
            message.AppendLine(stdError);
        }

        if (stdOutput.Length != 0)
        {
            message.AppendLine("Std output:");
            message.AppendLine(stdOutput.ToString());
        }

        throw new Exception(Format(filename, arguments) + " finished with exit code = " + process.ExitCode + ": " + message);
    }
}

private string Format(string filename, string arguments)
{
    return "'" + filename + 
        ((string.IsNullOrEmpty(arguments)) ? string.Empty : " " + arguments) +
        "'";
}


一个非常全面的例子,谢谢
在我看来,这是一个比接受的答案更全面的解决方案.我现在正在使用它,并没有使用已接受的那个,但那个看起来真的很缺乏.
可能想将OutputDataReceived处理程序更改为stdOut.AppendLine()

5> Jeff Mc..:
 System.Diagnostics.ProcessStartInfo psi =
   new System.Diagnostics.ProcessStartInfo(@"program_to_call.exe");
 psi.RedirectStandardOutput = true;
 psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
 psi.UseShellExecute = false;
 System.Diagnostics.Process proc System.Diagnostics.Process.Start(psi);;
 System.IO.StreamReader myOutput = proc.StandardOutput;
 proc.WaitForExit(2000);
 if (proc.HasExited)
  {
  string output = myOutput.ReadToEnd();
 }



6> Cameron..:

此页面上接受的答案有一个在极少数情况下很麻烦的弱点.有两个文件句柄,程序按惯例,stdout和stderr写入.如果您只是读取单个文件句柄(例如Ray的答案),并且您正在开始的程序将足够的输出写入stderr,它将填充输出stderr缓冲区并阻塞.然后你的两个进程陷入僵局.缓冲区大小可以是4K.这在短期程序中极为罕见,但如果你有一个长期运行的程序,它反复输出到stderr,它最终会发生.调试和跟踪这很棘手.

有几种很好的方法可以解决这个问题.

    一种方法是执行cmd.exe而不是程序,并使用cmd.exe的/ c参数调用程序以及cmd.exe的"2>&1"参数,告诉它合并stdout和stderr.

            var p = new Process();
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.Arguments = "/c mycmd.exe 2>&1";
    

    另一种方法是使用一个同时读取两个句柄的编程模型.

            var p = new Process();
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.Arguments = @"/c dir \windows";
            p.StartInfo.CreateNoWindow = true;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.RedirectStandardInput = false;
            p.OutputDataReceived += (a, b) => Console.WriteLine(b.Data);
            p.ErrorDataReceived += (a, b) => Console.WriteLine(b.Data);
            p.Start();
            p.BeginErrorReadLine();
            p.BeginOutputReadLine();
            p.WaitForExit();
    



7> Marc Gravell..:

您将需要使用ProcessStartInfoRedirectStandardOutput启用-那么你可以读取输出流.您可能会发现使用">"将输出重定向到文件(通过操作系统)更容易,然后只需读取文件即可.

[编辑:像雷一样:+1]


这会强制您在需要权限的地方编写文件,需要查找位置和名称,并且在完成后不得忘记删除.实际上更容易使用`RedirectStandardOutput`.
推荐阅读
保佑欣疼你的芯疼
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有