1

I have a server which receives commands from a client and runs them. These commands use one specific batch script, which receives arguments and runs. The script calls an external console application program with these arguments. The arguments can also instruct the script to run multiple instances of the console application, in the background. So, the outcome could be one open CMD, running 3 instances of app.exe, in the background.

I wish to know when each one of those processes of app.exe finish (and get each one's specific command line with its arguments), and send that to the client.

Any ideas?

svick
  • 236,525
  • 50
  • 385
  • 514
Idanis
  • 1,918
  • 6
  • 38
  • 69

3 Answers3

2

have you thought about calling this script from a backgound worker?

You backgoundworker would execute something like this:

static void ExecuteCommand(string command)
{
    int exitCode;
    ProcessStartInfo processInfo;
    Process process;

    processInfo = new ProcessStartInfo("cmd.exe", "/c " + command);
    processInfo.CreateNoWindow = true;
    processInfo.UseShellExecute = false;
    // *** Redirect the output ***
    processInfo.RedirectStandardError = true;
    processInfo.RedirectStandardOutput = true;

    process = Process.Start(processInfo);
    process.WaitForExit();

    // *** Read the streams ***
    string output = process.StandardOutput.ReadToEnd();
    string error = process.StandardError.ReadToEnd();

    exitCode = process.ExitCode;

    Console.WriteLine("output>>" + (String.IsNullOrEmpty(output) ? "(none)" : output));
    Console.WriteLine("error>>" + (String.IsNullOrEmpty(error) ? "(none)" : error));
    Console.WriteLine("ExitCode: " + exitCode.ToString(), "ExecuteCommand");
    process.Close();
}

static void Main()
{
    ExecuteCommand("echo testing");
}  

This way you can test if the process is done by checking the BackgroundWorker.IsBusy state. You can even update the user when ever the process finishes.

Hope this helps!

  • Thanks for the assistance, first of all. I am using Process.Start. However, I am running a main process and it calls 1 or more sub processes. The case of 1 sub process will work with the code you wrote here, because when the sub process terminates, so does the parent process. But If I run 2 or more processes together, the parent process will terminate only after both two sub processes terminate. I wish to know when each sub process terminates, so I guess that has something to do with constantly getting this information from the server computer's task manager. Am I wrong? – Idanis Feb 05 '13 at 15:37
0

If you start your processes with Process.Start it should return a Process object you can use to keep track of the lifetime, and with the properties HasExited and ExitTime you can determine if it over and when it finished.

Carlos Grappa
  • 2,351
  • 15
  • 18
0

It's not very clear in your questions, but I am assuming that you want to monitor processes that are started by another process. In other words, it doesn't make sense to use Process.Start() for them.

You can use Process.GetProcessByName() to get a list of running processes based on application name.

When you have that, you can use the Exited event to find out when does the process exit (you also have to set EnableRaisingEvents). For example:

var processes = Process.GetProcessesByName(processName);
foreach (var process in processes)
{
    Console.WriteLine("{0} running.", process);
    process.Exited += (sender, e) => Console.WriteLine("{0} exited.", sender);
    process.EnableRaisingEvents = true;
}

Be aware that there is a race condition: if the process exits after the call to GetProcessesByName() but before you set up the event handler, the Exited event might not be raised.

Another problem is how to figure out when is the application started. I am not aware of anything that would allow you to monitor newly started processes, so I think you will have to repeatedly call GetProcessesByName(), until you get the answer you're expecting.

svick
  • 236,525
  • 50
  • 385
  • 514