Как использовать «<» (перенаправление ввода) с ProcessStartInfo в C #? - PullRequest
2 голосов
/ 27 января 2012

У меня есть следующее:

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);
}

и мой dowork.exe падает после вызова Start ().

Любойпредложения?

Обновление после вопроса.

Спасибо всем за ваш вклад.Я решил проблему, используя ответ amit_g.Большое спасибо Филу за то, что он показал, вероятно, лучший способ (хотя я не проверял его, я понимаю, почему он лучше).Ниже мое полное решение.Не стесняйтесь копировать и изменять для своей собственной проблемы.

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 голосов
/ 27 января 2012

Вы должны использовать перенаправление 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);
}
4 голосов
/ 27 января 2012

Вы хотите сделать что-то вроде,

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);
1 голос
/ 27 января 2012

Это можно сделать, по крайней мере, несколько «хакерским» способом, передав аргументы непосредственно в cmd.exe.Однако, как , я рекомендую эмулировать «<» вручную, как и в других ответах, это здесь только для заметки. </p>

(foo.txt содержит две строки, «b» и«а», чтобы они были перевернуты при правильной сортировке)

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

Вы можете заменить /k на /c, чтобы cmd.exe не оставался открытым.(См. cmd /? для вариантов).

Удачного кодирования.

0 голосов
/ 27 января 2012

Во-первых, вам не нужно пробела, предшествующего вашим аргументам.Метод делает это для вас.Это может запутать вас с самого начала.Таким образом, это будет:

processArguments = "< input.txt";

Но если это не сработает, вы можете попробовать ::

process = "cmd.exe";
processArguments = "/c dowork.exe < input.txt";
...