I am trying to redirect the output of my command line program when it is called with Process.Start(). I've tried all permutations of RedirectStandardOutput, UseShellExecute and CreateNowWindow and had no luck.
I know there are other ways of accomplishing this such as reading StandardOutput after this but I would prefer to redirect it with arguments if possible into a file. I only care about the return code and only need the output of myprog.exe to go to a file. My program doesn't need to know what the output is.
var p = new Process();
p.StartInfo.FileName = #"myprog.exe";
p.StartInfo.Arguments = " " + InputFilename + " > " + OutputFilename;
p.StartInfo.RedirectStandardOutput = false;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.Start();
p.WaitForExit();
var result = p.ExitCode;
This will work for my issue. Get the output with p.StandardOutput.ReadToEnd() and write it to a file.
Related
I'm trying to run a batch file with arguments and also redirect the output.
When I don't redirect the output and use UseShellExecute = true, the batch file runs with the arguments as expected.
When I use UseShellExecute = false (to do the redirect), then I see that the command-line opens for a split a second and then closes.
I've read the output, using string output = proc.StandardOutput.ReadToEnd();
and I see that it contains the batch file content...
Can someone help me understand why it happens?
Thank you for your help :)
Here's the relevant code:
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo.CreateNoWindow = false;
proc.EnableRaisingEvents = false;
// the command
proc.StartInfo.FileName = command;
// the parameters of the command
proc.StartInfo.Arguments = args;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
try
{
// in case there is missing '"'
if (isContainQuote && index < 0)
{
str = "missing '\"' in the command " + commandStr;
}
else
{
proc.Start();
string output = proc.StandardOutput.ReadToEnd();
if (bWaitForExit)
{
proc.WaitForExit(m_SHELL_CMD_TIMEOUT);
str = "Succeed to run the command: " + commandStr + ", Output: " + proc.StandardOutput.ReadToEnd();
}
else
{
str = "Succeed to run the command: " + commandStr;
}
}
}
catch (Exception e)
{
str = e.Message + ". Failed to run the command: " + commandStr;
// return the error from the operation system
}
Seeing your batch file could help. By default batch files echo their commands to standard out.
Try adding an #ECHO OFF command to the beginning of the batch file to be sure that the batch file commands aren't echoed to the standard output.
I've been messing around with C# and in one moment of the code, I need to dump the output of an external .exe into a .txt. I do it by starting cmd.exe and then loading the program, with its attributes plus the > opperator. But now, when I execute the program, the file isn't even created. Meanwhile, if I input the EXACT same code that is passed to cmd in the program:
"o:\steam\steamapps\common\counter-strike global offensive\bin\demoinfogo.exe" "O:\Steam\SteamApps\common\Counter-Strike Global Offensive\csgo\testfile.dem" -gameevents -nofootsteps -deathscsv -nowarmup > "o:\steam\steamapps\common\counter-strike global offensive\demodump.txt"
directly into the Command Prompt, it does get dumped. I've been looking around, and I found A LOT of info, but sadlly nothing has helped me enough so far, so I decided to ask myself.
I attach the chunks of code that I think are relevant to this.
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = true;
startInfo.FileName = "CMD.exe";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
if (checkBox1.Checked)
{
arguments += " -gameevents";
if (checkBox2.Checked)
{
arguments += " -nofootsteps";
}
if (checkBox3.Checked)
{
arguments += " -extrainfo";
}
}
if (checkBox4.Checked)
{
arguments += " -deathscsv";
if (checkBox5.Checked)
{
arguments += " -nowarmup";
}
}
if (checkBox6.Checked)
{
arguments += " -stringtables";
}
if (checkBox7.Checked)
{
arguments += " -datatables";
}
if (checkBox8.Checked)
{
arguments += " -packetentites";
}
if (checkBox9.Checked)
{
arguments += " -netmessages";
}
if (dumpfilepath == string.Empty)
{
dumpfilepath = getCSGOInstallationPath() + #"\demodump.txt";
}
baseOptions = #"""" + demoinfogopath + #"""" + " " + #"""" + demofilepath + #"""" + arguments;
startInfo.Arguments = baseOptions + " > " + #"""" + dumpfilepath + #"""";
try
{
using (exeProcess = Process.Start(startInfo))
....a bunch of code...
The Process class that you're creating has this useful little property:
Process.StandardOutput
When a Process writes text to its standard stream, that text is normally displayed on the console. By redirecting the StandardOutput stream, you can manipulate or suppress the output of a process. For example, you can filter the text, format it differently, or write the output to both the console and a designated log file.
All you need to do is ensure you're redirecting the StandardOutput to this stream (using the RedirectStandardOutput property in the ProcessStartInfo) and then you can read the output from that stream. Here's the MSDN sample code, slightly abridged:
Process myProcess = new Process();
ProcessStartInfo myProcessStartInfo = new ProcessStartInfo(args[0], "spawn");
myProcessStartInfo.UseShellExecute = false; // important!
myProcessStartInfo.RedirectStandardOutput = true; // also important!
myProcess.StartInfo = myProcessStartInfo;
myProcess.Start();
// Here we're reading the process output's first line:
StreamReader myStreamReader = myProcess.StandardOutput;
string myString = myStreamReader.ReadLine();
Console.WriteLine(myString);
If you look at the help for CMD (access by typing CMD /?) you'll see the following options:
/C Carries out the command specified by string and then terminates
/K Carries out the command specified by string but remains
Without one of those switches, CMD won't interpret the string you provide it as a command to execute.
When I write a short program like the following, it successfully generates a file... but only if I use either the /C or /K options:
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = true;
startInfo.FileName = "CMD.exe";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
var command = #"echo test > c:\users\myusername\Desktop\test.txt";
var args = "/C " + command;
startInfo.Arguments = args;
using (var process = Process.Start(startInfo)) { }
//Hi you could try this to build your process like this.
public class Launcher
{
public Process CurrentProcess;
public string result = null;
public Process Start()
{
CurrentProcess = new Process
{
StartInfo =
{
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
RedirectStandardInput = true,
WorkingDirectory = #"C:\",
FileName = Path.Combine(Environment.SystemDirectory, "cmd.exe")
}
};
CurrentProcess.Start();
return CurrentProcess;
}
//Start the process to get the output you want to add to your .txt file:
private void writeOuput()
{
Currentprocess = new process();
Start()
CurrentProcess.StandardInput.WriteLine("Your CMD");
CurrentProcess.StandardInput.Close();
result = CurrentProcess.StandardOutput.ReadLine();
CurrentProcess.StandardOutput.Close()
//Then to put the result in a .txt file:
System.IO.File.WriteAllText (#"C:\path.txt", result);
}
}
}
Currently struggling to get this process working:
const string pdfkPath = "pdftk.exe";
var paths = new List<string>();
paths.Add(#"C:\test.pdf");
paths.Add(#"C:\testje.pdf");
var cmd = String.Join(" ", paths) + " cat output " + #"C:\lel.pdf";
Process p = new Process();
p.StartInfo.WorkingDirectory = Environment.CurrentDirectory;
p.StartInfo.FileName = pdfkPath;
p.StartInfo.Arguments = cmd;
p.StartInfo.UseShellExecute = false;
p.Start();
p.WaitForExit();
Executing the exe file with the arguments using command line works, so what am I doing wrong here?
Thanks!
Found it ourselves! The problem was the output being directly on the C:\, folder between fixed it
I have this BAT file "iARP.BAT"
Content Begin
#ECHO OFF
npg -vv -f %1 -d %2
Content End
And I'm trying to pass a file name (in a loop) as the first argument and device name (variable previously declared) as the second argument. I'm trying to do this:
for (int i = 1; i < arpFiles.Count; i++) {
p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.WorkingDirectory = Application.StartupPath;
p.StartInfo.FileName = Application.StartupPath + "\\iARP.bat";
String argument1 = Application.StartupPath + "\\" + arpFiles[0].Name;
p.StartInfo.Arguments = argument1 + deviceName;
p.StartInfo.Verb = "runas";
p.StartInfo.CreateNoWindow = true;
p.Start();
}
BTW arpFiles = List
but it is not executing can anyone help me with this?
You need to specify them all in the Arguments property:
p.StartInfo.Arguments = string.Format("{0} {1}", argument1, argument2);
All I am trying to do is send a command that opens a model with the program.exe
Supposed to be super simple!
Ex:
"C:\Program Files (x86)\River Logic\Enterprise Optimizer 7.4 Developer\EO74.exe" "C:\PauloXLS\Constraint Sets_1.cor"
The line above works well if pasted on the command prompt window.
However, when trying to pass the same exact string on my code it gets stuck on C:\Program
string EXE = "\"" + #tbx_base_exe.Text.Trim() + "\"";
string Model = "\"" + #mdl_path.Trim()+ "\"";
string ExeModel = EXE + " " + Model;
MessageBox.Show(ExeModel);
ExecuteCommand(ExeModel);
ExeModel is showing te following line on Visual Studio:
"\"C:\\Program Files (x86)\\River Logic\\Enterprise Optimizer 7.4 Developer\\EO74.exe\" \"C:\\PauloXLS\\Constraint Sets_1.cor\""
To me looks like it is the string I need to send in to the following method:
public int ExecuteCommand(string Command)
{
int ExitCode;
ProcessStartInfo ProcessInfo;
Process Process;
ProcessInfo = new ProcessStartInfo("cmd.exe", "/K " + Command);
ProcessInfo.CreateNoWindow = true;
ProcessInfo.UseShellExecute = true;
Process = Process.Start(ProcessInfo);
Process.WaitForExit();
ExitCode = Process.ExitCode;
Process.Close();
return ExitCode;
}
Things I've tried:
Pass only one command at a time (works as expected), but not an option since the model file will open with another version of the software.
Tried to Trim
Tried with # with \"
Can anyone see any obvious mistake? Thanks.
It's pretty straightforward. You just create a command line object then write to it, then to execute it you read back from it using SR.ReadToEnd():
private string GETCMD()
{
string tempGETCMD = null;
Process CMDprocess = new Process();
System.Diagnostics.ProcessStartInfo StartInfo = new System.Diagnostics.ProcessStartInfo();
StartInfo.FileName = "cmd"; //starts cmd window
StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
StartInfo.CreateNoWindow = true;
StartInfo.RedirectStandardInput = true;
StartInfo.RedirectStandardOutput = true;
StartInfo.UseShellExecute = false; //required to redirect
CMDprocess.StartInfo = StartInfo;
CMDprocess.Start();
System.IO.StreamReader SR = CMDprocess.StandardOutput;
System.IO.StreamWriter SW = CMDprocess.StandardInput;
SW.WriteLine("#echo on");
SW.WriteLine("cd\\"); //the command you wish to run.....
SW.WriteLine("cd C:\\Program Files");
//insert your other commands here
SW.WriteLine("exit"); //exits command prompt window
tempGETCMD = SR.ReadToEnd(); //returns results of the command window
SW.Close();
SR.Close();
return tempGETCMD;
}
Why are you opening a command prompt (cmd.exe)? Just pass the name of the executable.