Capture command line output in C#
Did you ever execute a console application in C# and wanted to capture the command line output?
You’re here to find the answer.
You have a long running console application and want to create an UI for it. You don’t have the oppurtunity to integrate the console application as a library so you’re bound to run the executeable. You want to be able to spawn multiple processes at the same time and be able to limit the concurrent execution of the processes. You need to be able to set EnvironmentVariables for the process environment. You need to be able to respond to new lines on the StandardError and StandardInput. You might need to respond to the console application with input.
The .Net Framework offers a handy class that allows most of the requirements the scenario holds. The class is called System.Diagnostics.Process. After I’m finished you will have a nice wrapper around the Process class that can be used in many different scenarios. How is the process class helping us? It’s pretty simple, the Process class is used to start a new process. You need to specify some information in the form of a ProcessStartInfo object and call the Start method on the Process.
Why do we need a wraper?
Since .Net Framework 4.5 we can use the TAP (Task-based Asynchronous Pattern) and that’s what I’m gonna faciliate to get a class that can be inherited for your own needs and allows you to run multiple instances of the application.
First we need the LimitedConcurrencyTaskScheduler I’ve provided in an earlier post. If you didn’t read that post yet go there now and atleast get the code set up in your project. While you do so leave a comment about your expirience.
Since we need a clean way to interact with the process we define an interface. This interface defines a set of properties that allow you to react to updates from the application. It also defines a set of methods that are used to generate the input for the application.
Now that we have sepcified our Environment Builder Interface we are ready to implement our BaseProcess class.
The BaseProcess Class
The BaseProcess class specifies some static properties and a set of static methods. Since it is an abstract generic class those static properties and methods will be initialized per implementation. The static members are used for parallelization, we define our LimitedConcurrencyTaskScheduler used for scheduling our child processes and a LinkedList that will hold our processes. The static Start methods provide a way to enqueue a new process to the queue. The argument for that methods will be our environment builders. Our class defines two properties, the command line of the process to run and the environment that will be used during execution. The two fields are used to generate the console output, one for locking the StringBuilder and one to generate the output. The constructor of the class sets the command line so make sure to specify it in your implementation class. The protected Execute method does the actual work of spawning the new child process. The private methods are handlers for some of the events triggered by the System.Diagnostics.Process class. Those memebers will call the abstract members defined in the class.
So Now that we have the Base Process class ready we can start to make use of it in one of our projects.
This post is also available in: German