How to write Process.Start and get the ExitCode in one line? - c#

Many examples and MSDN are using a new Process to get the exitcode, however, creat a new variable looks not so grace.So, I tried this
Process.Start("Application.exe", "parameter").WaitForExit().ExitCode
aimed to get the exitcode in one line but failed.
And is there any solution of this writing?

It doesn't work like that because WaitForExit() returns a bool, which doesn't have an ExitCode property. If you want this behavior on one line, you'll have to implement it yourself in a method and call it.
public int RunAndGetCode(string executable, string parameter)
{
var process = Process.Start(executable, parameter).WaitForExit();
return process.ExitCode;
}
// then later
var code = RunAndGetCode("Application.exe", "parameter");

So... That's not quite how Process works. You could write a wrapper class that allows you to do it in one one line, or using a using block, but when you have to wait for any process, that means you're locking up your own process while waiting for it. In Windows that is terrible practice.
The way it's designed in C#, it allows your own process to do other work while the process you called has returned. (Wrote this on mobile device; apologies for errors)
So, in short, no, but I see nothing wrong with this:
Process p = new Process();
P.Start();
While(!p.WaitForExit()) {
//do work while you wait for the calling process to return
}
var exitCode = p.ExitCode

Related

How to pass values from a process being called

In the main method I want to start a process which is to run some test cases, and when the process returns I want to know how many test cases failed. In this case, I want the process to be able to return a value to the main process after it is done executing. Is there a way to do this? My code is like below:
ProcessStartInfo processInfo = new ProcessStartInfo(exeFilePath, Parser.Default.FormatCommandLine(options));
var p = Process.Start(processInfo);
// need to get the number of failed test cases from the process
Any help is appreciated.

load and execute external program (many times)

I need to execute external program with arguments and get result from it (~1000 times with different arguments).
I found solution like this:
using System.Diagnostics;
...
Process process = new Process();
// Configure the process using the StartInfo properties.
process.StartInfo.FileName = "process.exe";
process.StartInfo.Arguments = "qwe 123";
process.Start();
process.WaitForExit();// Waits here for the process to exit.
// And check exit code for result
I need many repetitions with different arguments, but this code every time initiate new process. It is very expensive operation. I think, i can "load" ("save") process and repeat it without everytime initiating.
Or maybe exist other way to solve this problem?
If the started process is under your control it will be much more efficient to pass the input not via command line parameter for a new process instance every time, but re-program it so that the process reads its standard input line-wise in a loop, processes each line, and writes the result to its standard output. It's easy to hook up the calling program to the process' input and output:
// ...
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardInput = true;
// ...
process.Start();
StreamReader results = process.StandardOutput;
StreamWriter processInput = process.StandardInput;
foreach( var arg in args )
{
processInput.WriteLine(arg);
var oneResult = results.ReadLine();
// do something with this oneResult
}
This example assumes that each argument fits in one line (and each result fits in a line, too). Writing and reading a single line each time is our simple "protocol" for knowing when to start processing (on the process side) and when the result is complete (on the C# side).
I should perhaps add that a real program should add error handling and e.g. evaluate Process.Start()'s return value.

C# equivalent to fork()/exec()

I'm developing a program that needs to call an outside program, but needs to wait for it to execute. This is being done in C# (to which I am brand new, but have lots of experience in C++, Qt, and C) and CreateProcess does not seem to be what I'm looking for (starts the process, then forgets it, which I don't need).
This is one of my first Windows projects (or at least, only Windows and definitely only .NET) and I'm much more used to doing this sort of thing for *nix where I would use fork and then exec in the child, then wait for the child to terminate. But I have no idea where to even start looking to do something like this.
Oh, and I'm pretty sure I'm stuck in .NET because I need read access to the registry to complete this project and .NET's registry access is absolutely amazing (in my opinion, I don't have anything to compare it to).
Thanks.
You can use the Process class. It lets you specify some options about how you want to execute it, and also provides a method which waits the process to exit before executing the next statement.
look at this link (the msdn reference):
http://msdn.microsoft.com/fr-fr/library/system.diagnostics.process.aspx
basically what you can do is:
Process p;
// some code to initialize it, like p = startProcessWithoutOutput(path, args, true);
p.WaitForExit();
an example of initializing the process (that's just some code I used once somewhere):
private Process startProcessWithOutput(string command, string args, bool showWindow)
{
Process p = new Process();
p.StartInfo = new ProcessStartInfo(command, args);
p.StartInfo.RedirectStandardOutput = false;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = !showWindow;
p.ErrorDataReceived += (s, a) => addLogLine(a.Data);
p.Start();
p.BeginErrorReadLine();
return p;
}
as you can see in this code you can also do some output redirection, error redirection.... If you dig in the class I think you'll find quite quickly what you need.
var p = System.Diagnostics.Process.Start("notepad");
p.WaitForExit();
You can use the Process class to start external processes.
It will let you start arbitrary programs
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.aspx

ReadToEnd from std output of process and waitforexit

From the MSDN example of using stdoutput of newly created process:
// This is the code for the base process
Process myProcess = new Process();
// Start a new instance of this program but specify the 'spawned' version.
ProcessStartInfo myProcessStartInfo = new ProcessStartInfo(args[0], "spawn");
myProcessStartInfo.UseShellExecute = false;
myProcessStartInfo.RedirectStandardOutput = true;
myProcess.StartInfo = myProcessStartInfo;
myProcess.Start();
StreamReader myStreamReader = myProcess.StandardOutput;
// Read the standard output of the spawned process.
string myString = myStreamReader.ReadLine();
Console.WriteLine(myString);
myProcess.WaitForExit();
myProcess.Close();
If instead of myStreamReader.ReadLine() I'm using myStreamReader.ReadToEnd() shall I still use myProcess.WaitForExit()?
Or ReadToEnd() will wait until the process is finished?
EDIT:
Sorry for the diversion, to directly answer your question. Yes, you need to call Process.WaitForExit();. This will ensure that the process has yielded all its output before you call ReadToEnd()
ReadToEnd is synchronous function. Hence if you don't call it in your code, it will block your main thread until it captures only the first output from the StandardOutput, then that's it. But using WaitForExit will ensure that you have everything.
Also you might consider doing an asynchronous read of the process's output, see this MSDN Example that implements OutputDataRecieved
"ReadToEnd" is a function stored in "StreamReader" object and I don't think it has something to do with waiting for a process to exit, however the "Process" class might handle that itself. By the way, all the abilities "StreamReader" has are not useful in the situation you mentioned.
In my point of view, "WaitForExit" should be called and as you did "Close" too. Because they will release some system resources that no method else can. As far as I know, "ReadToEnd" method has nothing to do with calling those two.
Cheers

Is there any alternative other than Process to execute built-in shell commands in C#

Is there any alternative other than Process to execute built-in shell commands in C#? Currently I am using Process class to run those commands. But in the current scenario I want to run more than 200 such commands in parallel. So spawning more than 200 processes is not a good idea. Is there any other alternative?
"Running a dos command" is the equivalent to "Creating a process and running it" so even if there is an other api, there will still be 200 processes (which, by the way, is nothing to worry about unless you're on a really, really tiny system)
You could but, shouldn't do
using Microsoft.VisualBasic;
Interaction.Shell(...);
Note: You would have to add a reference to the the VisualBasic assembly.
This is a direct answer to your question but, not somthing you should do.
As Max Keller pointed out, System.Diagnostics.Process always starts a new system process.
If have to start processes/operations for more than just some seconds, I would prefer to save all commands in a temp file and execute this with System.Diagnostics.Process rather than ever single operation.
// Get a temp file
string tempFilepath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "MyBatchFile.bat");
// Ensure the file dont exists yet
if (System.IO.File.Exists(tempFilepath)) {
System.IO.File.Delete(tempFilepath);
}
// Create some operations
string[] batchOperations = new string[]{
"START netstat -a",
"START systeminfo"
};
// Write the temp file
System.IO.File.WriteAllLines(tempFilepath, batchOperations);
// Create process
Process myProcess = new Process();
try {
// Full filepath to the temp file
myProcess.StartInfo.FileName = tempFilepath;
// Execute it
myProcess.Start();
// This code assumes the process you are starting will terminate itself!
} catch (Exception ex) {
// Output any error to the console
Console.WriteLine(ex.Message);
}
// Remove the temp file
System.IO.File.Delete(tempFilepath);

Categories

Resources