Frage

I have the following:

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

I try this:

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

and my dowork.exe crashes after Start() is called.

Any suggestions?

Post Question Update.

Thank you everyone for your input. I solved the problem using amit_g's answer. Extended thanks to Phil for showing likely the best way (although I didn't test it out, I can see why it is better). Below is my complete solution. Feel free to copy and modify for your own issue.

1) create a console application project, add this class

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) Create 1 file: C:\temp\input.txt

3) edit input.txt, type a single letter 'w' and save (that's right the file contains a single letter).

4) Create a new class library project. Add a reference to nunit (i'm using version 2.2).

5) Create a testfixture class, it should look like the following. Note: this test fixture is handling external resources, as such you cannot run the entire fixture, instead, run each test one-at-a-time. You can fix this by making sure all file streams are closed, but i didn't care to write this, feel free to extend it yourself.

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


}

}

War es hilfreich?

Lösung

You have to use the STDIN redirection. Like this...

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

Andere Tipps

You are going to want to do something like,

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

This can be done, at least in a somewhat "hacky" fashion by passing arguments directly to cmd.exe. However, as I recommend emulating the "<" manually as in the other answers, this is here as a note only.

(foo.txt is contains two lines, "b" and "a", so that they will be reversed when correctly sorted)

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

You can replace /k with /c to prevent cmd.exe from remaining open. (See cmd /? for the options).

Happy coding.

First, you don't need a space preceeding your args. The method does it for you. This might mess you up to begin with. So it would be:

processArguments = "< input.txt";

But if that doesn't work you can try::

process = "cmd.exe";
processArguments = "/c dowork.exe < input.txt";
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top