3

我有以下内容:

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

4 回答 4

5

您必须使用 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);
}
于 2012-01-26T20:12:17.650 回答
5

你会想要做类似的事情,

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);
于 2012-01-26T20:12:27.323 回答
1

这可以通过将参数直接传递给 cmd.exe 来完成,至少以某种“hacky”的方式完成。但是,正如我建议在其他答案中手动模拟“<”一样,这仅作为说明。

(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 /?选项)。

快乐编码。

于 2012-01-26T20:12:42.960 回答
0

首先,您不需要在 args 之前有空格。该方法为您完成。这可能会让你一开始就搞砸。所以它会是:

processArguments = "< input.txt";

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

process = "cmd.exe";
processArguments = "/c dowork.exe < input.txt";
于 2012-01-26T20:11:40.857 回答