Process.Start(processInfo) response is blank - c#

I need to invoke an exe using System.Diagnostics.Process.Start(processInfo) and want to get some value return back.Based on return value i need to perform further operation. Exe is getting invoked and performing the task accurately, but i am not able to get return value back. Code gets stuck after process.Start() no exception or warning.
string arguments = arg[0]+ " " + arg[1] + " " + arg[2] + " " + arg[3];
string consoleExePath = #"C:\Test\Console.exe";
ProcessStartInfo processInfo = new ProcessStartInfo();
processInfo.WindowStyle = ProcessWindowStyle.Hidden;
processInfo.FileName = "cmd.exe";
processInfo.RedirectStandardOutput = true;
processInfo.UseShellExecute = false;
processInfo.WorkingDirectory = Path.GetDirectoryName(consoleExePath);
processInfo.Arguments = string.Format("/c START {0} {1}", Path.GetFileName(consoleExePath), arguments);
System.Diagnostics.Process p = System.Diagnostics.Process.Start(processInfo);
var output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
int result = p.ExitCode; // always 0
Code inside exe:
static int Main(string[] args)
{
var flag = 0;
flag= objTest.DoSomething(args[0],args[1], args[2], args[3]);
//Console.WriteLine("Process completed!");
//Console.Read();
//return flag;
return 44; // a non zero value.
}
Edit: Due to Console.Read();, code execution got stuck. thanks to schnaader for catching the silly mistake. But var output = p.StandardOutput.ReadToEnd(); is still empty. tried int result = p.ExitCode; and result is always 0.

Your code works for me. Note that in your .exe code, there is a line:
Console.Read();
So the program will wait for the user to enter a line, and only exit after that. If you don't do this, the other code will wait for the application to terminate like you described.
So you should remove that line and try again.
Another possibility that Christian.K noted in the comments is to redirect standard input using processInfo.RedirectStandardInput = true. This way, you won't have to modify the .exe code. After that, you can redirect things to the standard input of your .exe, see MSDN for a full example.

Related

Process.Start() totally ignore the environment variables in PATH

I found that my cmd window prompted by Process.Start() totally ignore my environment variables in PATH. It always said that "xxx is not internal or external commands". I tried run it manually and it worked. Therefore, I am sure the PATH has been set correctly.
I also tried to add the variable explicitly. It still did not work.
This is my code:
public static string ExecuteCommandSync(string command)
{
try
{
System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("C:\\Windows\\System32\\cmd.exe", "/K " + command);
var length = command.Length;
procStartInfo.RedirectStandardOutput = false;
procStartInfo.UseShellExecute = false;
//Does not work
procStartInfo.EnvironmentVariables.Add("PATH", "C:\\Program Files\\Arm\\Arm Mobile Studio 2021.0");
procStartInfo.CreateNoWindow = false;
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
}
catch (Exception objException)
{
return objException.ToString();
}
}
It is better when you did add the complete description of the error, in stead of "does not work"
System.ArgumentException: Value does not fall within the expected
range. at
System.Collections.Specialized.StringDictionaryWrapper.Add(String key,
String value) at ConsoleApp88.Program.ExecuteCommandSync(String
command) in
You cannot add PATH because it is already in the list of environment variables.
Solution can be to add the next statement, just before the add:
procStartInfo.EnvironmentVariables.Remove("PATH");

C# Process.StandardError reading without blocking

I am a programming teacher and I am developing an automated checker for the students HWs (All are Console Apps). Basically, I run the student code using some Process.Start() (with some input file) and check if its output is as expected.
If, for some reason, the student code did no complete succesfully, I send them the exception thrown by their code using the process Standart Error redirection.
However, I want to do better then that. I want to find the input line written to the process StandartInput afterwhich their exception took place. How can I do that? My current code is more or less:
ProcessStartInfo psi = new ProcessStartInfo(students_exe_path);
psi.UseShellExecute = false;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
String randomInputFile = randomInputFilesFolder + "\\" + "test.txt";
psi.WorkingDirectory = randomInputFilesFolder;
Process p = Process.Start(psi);
StreamWriter inputWriter = p.StandardInput;
String[] inputLines = File.ReadAllLines(randomInputFile);
foreach (String line in inputLines)
{
// here I wanted to read the standart error so far (before writing next input line)
String errorTextBefore = p.StandardError.ReadToEnd(); // can not use this because blocks progress.
inputWriter.WriteLine(line); // sending next input line to students app
// here I wanted to read the standart error so far (after writing next input line)
String errorTextAfter = p.StandardError.ReadToEnd(); // can not use because blocks
if (errorTextBefore != errorTextAfter) Console.WriteLine("Line {0} caused the exception",line);
}
Or maybe I can check from p.StandartInput which text was not "consumed" by the process?
Tamir

C# process can not execute batch file (contain timeout command) correctly

I'd like to execute a batch file without showing terminal window
and I need to get the standard output contents.
Here is the batch file:
timeout /T 5
exit 0
Below is my partial C# code:
static void Main(string[] args)
{
bool ShowTerminal = true;
Process proc = new Process();
proc.StartInfo.FileName = "cmd.exe";
string ExecContent = "\"" + args[0] + "\"";
proc.StartInfo.Arguments = "/c " + ExecContent;
proc.StartInfo.UseShellExecute = ShowTerminal;
proc.StartInfo.RedirectStandardError = !ShowTerminal;
proc.StartInfo.RedirectStandardInput = !ShowTerminal;
proc.StartInfo.RedirectStandardOutput = !ShowTerminal;
proc.Start();
proc.WaitForExit();
}
I found that variable ShowTerminal set true, then everything is going well
except I can not get standard output contents
But if variable ShowTerminal set false, timeout command will be skipped
Is there any solution for this problem? Thanks!
If you specify "redirect" options you should also provide their redirection streams (STDIN, STDOUT) and ensure they are being emptied/read/processed as CMD would expect.
Chances are good that 'timeout' is failing to detect any STDIN/STDOUT and therefore performs a noop.

Using Process in java

I'm converting some c# code to java
System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);
// The following commands are needed to redirect the standard output.
// This means that it will be redirected to the Process.StandardOutput StreamReader.
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
// Do not create the black window.
procStartInfo.CreateNoWindow = true;
// Now we create a process, assign its ProcessStartInfo and start it
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
// Get the output into a string
string result = proc.StandardOutput.ReadToEnd();
// Display the command output.
This is the code that i try to convert it to java.
I dont know how to run a command and use process in java. I googled it and i found something like that :
Process process = Runtime.getRuntime().exec(command);
Integer result = process.exitValue();
In the line
process.exitValue()
it gives me java.lang.IllegalThreadStateException: process has not exited.
After exec you need to wait for the command to finish with process.waitFor().
process.exitValue() gets the number from System.exit(number)
The error is thrown since the process hasn't exited yet.
From the c# code it looks like you want to get the command's output, this can be done by:
int i=0;
String result = new String();
while((i = process.getInputStream().read()) >= 0)
result += (char)i;
System.out.println(result);

Git Pull from Batch file with different user

I have a user, let's call it "MyUser". It has a password, suppose it is "Password". This user has an SSH key for git. I try to run from my ASP.NET application a batch file which issues git commands, it is at a location which is passed as a parameter. My function is as follows:
private void ExecuteCommand(string path, int timeout)
{
Process process = new Process();
process.StartInfo = new ProcessStartInfo();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "\"" + path + "\"";
process.StartInfo.CreateNoWindow = true;
process.StartInfo.UseShellExecute = false;
//processInfo.WorkingDirectory = Config.GitHubRepoPath;
process.StartInfo.UserName = "MyUser";
process.StartInfo.Password = new System.Security.SecureString();
process.StartInfo.Password.AppendChar('P');
process.StartInfo.Password.AppendChar('a');
process.StartInfo.Password.AppendChar('s');
process.StartInfo.Password.AppendChar('s');
process.StartInfo.Password.AppendChar('w');
process.StartInfo.Password.AppendChar('o');
process.StartInfo.Password.AppendChar('r');
process.StartInfo.Password.AppendChar('d');
// *** Redirect the output ***
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
// *** Read the streams ***
string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
if (timeout <= 0)
{
process.WaitForExit();
}
else
{
process.WaitForExit(timeout);
}
int exitCode = process.ExitCode;
process.Close();
return new ShellCommandReturn { Error = error, ExitCode = exitCode, Output = output };
}
But when I run this function, the ExitCode is -1073741502 and error and output are empty. How can I fix this behavior?
Please help me, I have tried to solve this literally for days.
I think redirecting both standard error and standard output & attempts to consume both synchronously is wrong. Please see this link:
http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.redirectstandardoutput%28v=vs.100%29.aspx
Allow me to copy excerpt:
A deadlock condition results if the parent process calls p.StandardOutput.ReadToEnd followed by p.StandardError.ReadToEnd and the child process writes enough text to fill its error stream. The parent process would wait indefinitely for the child process to close its StandardOutput stream. The child process would wait indefinitely for the parent to read from the full StandardError stream.
The other thing is ... when you invoke a cmd.exe instance, try adding a "/c" argument too.

Categories