Could you please explain why the shell redirection doesn't work with System.Diagnostics.Process class? I am trying to redirect the output streams to file with the following snippet:
Process p = new Process();
p.StartInfo = new ProcessStartInfo();
p.StartInfo.FileName =开发者_如何学JAVA "java.exe";
p.StartInfo.Arguments = @"> c:\Temp\test.log 2>&1";
p.StartInfo.UseShellExecute = true;
p.Start();
The similar code works without problems with Python. Reading the output streams programmatically doesn't seem a preferable solution in my case because there will be a bunch of processes launched by my application.
You cannot do the redirection because there is no shell directly involved. You could run a cmd.exe session, but the proper way to do it is using the RedirectStandardOutput/Error properties. There is no problem when having many processes. This is a class I use for this.
class HandleExecutable {
private DataReceivedEventHandler outputHandler;
public DataReceivedEventHandler OutputHandler
{
set { outputHandler = value; }
}
private DataReceivedEventHandler errorHandler;
public DataReceivedEventHandler ErrorHandler
{
set { errorHandler = value; }
}
public void callExecutable(string executable, string args)
{
string commandLine = executable;
string args = args;
ProcessStartInfo psi = new ProcessStartInfo(commandLine);
psi.UseShellExecute = false;
psi.LoadUserProfile = false;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
psi.WindowStyle = ProcessWindowStyle.Minimized;
psi.CreateNoWindow = true;
psi.Arguments = args;
p = new Process();
p.StartInfo = psi;
try
{
p.Start();
p.BeginOutputReadLine();
p.BeginErrorReadLine();
if (outputHandler != null) p.OutputDataReceived += outputHandler;
if (errorHandler != null) p.ErrorDataReceived += errorHandler;
p.WaitForExit();
p.Close();
p.Dispose();
}
catch (Exception ex)
{
log.Error(ex.Message);
}
}
}
//On another class
void p_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
//HANDLE STDERR
if (e.Data != null && !e.Data.Equals(""))
{
if (!e.Data.Contains("Something")) {
}
}
}
void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
//HANDLE STDOUT
if (e.Data != null && !e.Data.Equals(""))
{
}
}
HandleExecutable he = new HandleExecutable();
he.OutputHandler = p_OutputDataReceived;
he.ErrorHandler = p_ErrorDataReceived;
he.callExecutable(@"C:\java.exe","-cp foo ClassName");
It is because there is no shell to process those arguments. When you type your command line to shell, it gets parsed, program arguments separated from the shell "special" modifiers, and only then launched. In C# this doesn't happen because there is no "cmd.exe" or "bash" process to do it.
To redirect input in C# you should set p.StartInfo.RedirectStandardOutput
to true, then use p.StandardOutput
to read data and then write it to a file.
Alternatively, you can run a "cmd.exe" with parameters required to execute the process and redirect its output. Although not cross-platform, this should be easier to do than to write efficient data stream passing implementation yourself.
If you want to redirect the output streams you have to configure it. Set the Redirect...
properties and read the streams. You can find an example here.
Regards
精彩评论