How to pass filename to StandardInput (Process) in

2019-09-01 01:02发布

问题:

I'm using the native windows application spamc.exe (SpamAssassin - sawin32) from command line as follows:

C:\SpamAssassin\spamc.exe -R < C:\email.eml

Now I'd like to call this process from C#:

Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.FileName = @"C:\SpamAssassin\spamc.exe";
p.StartInfo.Arguments = @"-R";
p.Start();

p.StandardInput.Write(@"C:\email.eml");
p.StandardInput.Close();
Console.Write(p.StandardOutput.ReadToEnd());
p.WaitForExit();
p.Close();

The above code just passes the filename as string to spamc.exe (not the content of the file). However, this one works:

Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.FileName = @"C:\SpamAssassin\spamc.exe";
p.StartInfo.Arguments = @"-R";
p.Start();

StreamReader sr = new StreamReader(@"C:\email.eml");
string msg = sr.ReadToEnd();
sr.Close();

p.StandardInput.Write(msg);
p.StandardInput.Close();
Console.Write(p.StandardOutput.ReadToEnd());
p.WaitForExit();
p.Close();

Could someone point me out why it's working if I read the file and pass the content to spamc, but doesn't work if I just pass the filename as I'd do in windows command line?

回答1:

It's cause on the command line the < is a little magic parameter. It just does a little bit more, then you maybe expect. In fact it opens the file and put its content into the standard input of the process. So that's the same you must do manually when using the Process class.

As you already showed in your second example you have to use a StreamReader to get the content of the file and put it into the StandardInput. Just to make it a little more robust you can maybe use this little code snippet:

using (var streamReader = new StreamReader(fileInfo.FullName))
{
    process.StandardInput.Write(streamReader.ReadToEnd());
    process.StandardInput.Flush();
}


回答2:

In the first example you are passing a string that represents the file not the file.



回答3:

Your first code sample is the equivalent of directing input from a file containing the line C:\email.eml:

echo C:\email.eml > inputfile
C:\SpamAssassin\spamc.exe -R < inputfile

Your second code sample passes the content of C:\email.eml to spamc.