如何使用“<” (输入重定向)与C#中的ProcessStartInfo?

时间:2012-01-26 20:01:03

标签: c# command-line-arguments processstartinfo

我有以下内容:

C:\temp\dowork.exe < input.txt
processing.......
complete
C:\

我试试这个:

processArguments = " < input.txt";
pathToExe = "C:\\temp\dowork.exe";
startInfo = new ProcessStartInfo
                {
                     FileName = pathToExe,
                     UseShellExecute = false,
                     WorkingDirectory = FilepathHelper.GetFolderFromFullPath(pathToExe),
                     Arguments = processArguments
                };

try
 {
    using (_proc = Process.Start(startInfo))
     _proc.WaitForExit();
 }
catch (Exception e)
  {
    Console.WriteLine(e);
}

并且调用Start()后我的dowork.exe崩溃。

有什么建议吗?

发布问题更新。

感谢大家的意见。我用amit_g的答案解决了这个问题。感谢Phil表示可能是最好的方式(尽管我没有测试它,我可以看到为什么它更好)。以下是我的完整解决方案。您可以随意复制和修改自己的问题。

1)创建一个控制台应用程序项目,添加此类

internal class DoWork
{
    private static void Main(string[] args)
    {
        var fs = new FileStream("C:\\temp\\output.txt", FileMode.Create, FileAccess.ReadWrite, FileShare.None);

        var toOutput = "Any items listed below this were passed in as args." + Environment.NewLine;
        foreach (var s in args)
            toOutput += s + Environment.NewLine;

        Console.WriteLine("I do work. Please type any letter then the enter key.");
        var letter = Console.ReadLine();
        Console.WriteLine("Thank you.");
        Thread.Sleep(500);

        toOutput += "Anything below this line should be a single letter." + Environment.NewLine;
        toOutput += letter + Environment.NewLine;

        var sw = new StreamWriter(fs);
        sw.Write(toOutput);

        sw.Close();
        fs.Close();
    }
}

2)创建1个文件:C:\ temp \ input.txt

3)编辑input.txt,输入单个字母'w'并保存(右边文件包含一个字母)。

4)创建一个新的类库项目。添加对nunit的引用(我使用的是2.2版)。

5)创建一个testfixture类,它应该如下所示。注意:此测试夹具正在处理外部资源,因此您无法运行整个夹具,而是一次一个地运行每个测试。您可以通过确保所有文件流都已关闭来解决此问题,但我不想写这个,请随意自行扩展。

using System.Diagnostics;
using System.IO;
using NUnit.Framework;

namespace Sandbox.ConsoleApplication
{
[TestFixture]
public class DoWorkTestFixture
{
    // NOTE: following url explains how ms-dos performs redirection from the command line:
    // http://www.febooti.com/products/command-line-email/batch-files/ms-dos-command-redirection.html

    private string _workFolder = "C:\\Temp\\";
    private string _inputFile = "input.txt";
    private string _outputFile = "output.txt";
    private string _exe = "dowork.exe";

    [TearDown]
    public void TearDown()
    {
        File.Delete(_workFolder + _outputFile);
    }

    [Test]
    public void DoWorkWithoutRedirection()
    {
        var startInfo = new ProcessStartInfo
                            {
                                FileName = _workFolder + _exe,
                                UseShellExecute = false,
                                WorkingDirectory = _workFolder
                            };

        var process = Process.Start(startInfo);
        process.WaitForExit();

        Assert.IsTrue(File.Exists(_workFolder + _outputFile));
    }

    [Test]
    public void DoWorkWithoutRedirectionWithArgument()
    {
        var startInfo = new ProcessStartInfo
                            {
                                FileName = _workFolder + _exe,
                                UseShellExecute = false,
                                WorkingDirectory = _workFolder,
                                Arguments = _inputFile
                            };

        var process = Process.Start(startInfo);
        process.WaitForExit();

        var outputStrings = File.ReadAllLines(_workFolder + _outputFile);

        Assert.IsTrue(File.Exists(_workFolder + _outputFile));
        Assert.AreEqual(_inputFile, outputStrings[1]);
    }

    [Test]
    public void DoWorkWithRedirection()
    {
        var startInfo = new ProcessStartInfo
                            {
                                FileName = _workFolder + _exe,
                                UseShellExecute = false,
                                WorkingDirectory = _workFolder,
                                RedirectStandardInput = true
                            };

        var myProcess = Process.Start(startInfo);
        var myStreamWriter = myProcess.StandardInput;
        var inputText = File.ReadAllText(_workFolder + _inputFile);

        myStreamWriter.Write(inputText);

        // this is usually needed, not for this easy test though:
        // myProcess.WaitForExit();

        var outputStrings = File.ReadAllLines(_workFolder + _outputFile);

        Assert.IsTrue(File.Exists(_workFolder + _outputFile));
        // input.txt contains a single letter: 'w', it will appear on line 3 of output.txt
        if(outputStrings.Length >= 3)  Assert.AreEqual("w", outputStrings[2]);
    }

    [Test]
    public void DoWorkWithRedirectionAndArgument()
    {
        var startInfo = new ProcessStartInfo
        {
            FileName = _workFolder + _exe,
            UseShellExecute = false,
            WorkingDirectory = _workFolder,
            RedirectStandardInput = true
        };

        var myProcess = Process.Start(startInfo);
        var myStreamWriter = myProcess.StandardInput;
        var inputText = File.ReadAllText(_workFolder + _inputFile);

        myStreamWriter.Write(inputText);
        myStreamWriter.Close();

        // this is usually needed, not for this easy test though:
        // myProcess.WaitForExit();

        var outputStrings = File.ReadAllLines(_workFolder + _outputFile);

        Assert.IsTrue(File.Exists(_workFolder + _outputFile));
        // input.txt contains a single letter: 'w', it will appear on line 3 of output.txt
        Assert.IsTrue(outputStrings.Length >= 3);
        Assert.AreEqual("w", outputStrings[2]);
    }


}

}

4 个答案:

答案 0 :(得分:4)

您必须使用STDIN重定向。像这样......

inputFilePath = "C:\\temp\input.txt";
pathToExe = "C:\\temp\dowork.exe";

startInfo = new ProcessStartInfo
                {
                     FileName = pathToExe,
                     UseShellExecute = false,
                     WorkingDirectory = FilepathHelper.GetFolderFromFullPath(pathToExe),
                     RedirectStandardInput = true
                };

try
{
    using (_proc = Process.Start(startInfo))
    {
        StreamWriter myStreamWriter = myProcess.StandardInput;

        // Use only if the file is very small. Use stream copy (see Phil's comment).
        String inputText = File.ReadAllText(inputFilePath);

        myStreamWriter.Write(inputText);
    }

    _proc.WaitForExit();
}
catch (Exception e)
{
    Console.WriteLine(e);
}

答案 1 :(得分:4)

您将要做类似的事情,

ProcessStartInfo startInfo = new ProcessStartInfo
{
    FileName = pathToExe,
    UseShellExecute = false,
    WorkingDirectory = FilepathHelper.GetFolderFromFullPath(pathToExe)
}; 


Process process = Process.Start(startInfo);
FileStream reader = File.OpenRead("input.txt");
reader.CopyTo(process.StandardInput.BaseStream);

答案 2 :(得分:1)

这可以通过将参数直接传递给cmd.exe来完成,至少以某种“hacky”方式完成。但是,正如我建议模仿“&lt;”手动和其他答案一样,这只是一个注释。

(foo.txt包含两行,“b”和“a”,以便在正确排序时它们会反转)

var x = new ProcessStartInfo {
    FileName = "cmd",
    Arguments = "/k sort < foo.txt",
    UseShellExecute = false,
};
Process.Start(x);

您可以将/k替换为/c,以防止cmd.exe保持打开状态。 (有关选项,请参阅cmd /?。)

快乐的编码。

答案 3 :(得分:0)

首先,你的args之前不需要空格。该方法适合您。这可能会让你陷入困境。所以它会是:

processArguments = "< input.txt";

但如果这不起作用,你可以试试::

process = "cmd.exe";
processArguments = "/c dowork.exe < input.txt";
相关问题