Friday, May 01, 2015

[ C# ] - Spawning a process & get notification on Completion

1. Introduction

A "Program" is an executable stored in the physical disc. Say for example Notepad.exe stored in windows System32 folder is called as "Notepad Program". When the program in secondary storage (Disc) loads into primary storage for the execution of instructions set in it, we call it as "Process". Windows has the capability of spawning multiple processes at a time and we call windows as a Multi-Tasking operating system. When all processes running in the background they compete for the shared resources. OK, in this article we are going to see how we can spawn a process from a C# application.

2. About the Example

The below screenshot shows the application example:

The sample application has two parts. The first part starts a notepad process when the “Start” (Marked as 1) button is clicked.  You can enter the text document location in the textbox (Marked as 2) before clicking the start button. When a text document is specified, the notepad process opens that document. In the second part, a batch file is started as the process by clicking the start button (Marked as 7). The batch file actually performs a "DOS copy" operation, which requires Source and destination locations. These data can be supplied through two text boxes (Marked as 3, 4). When a batch file execution continues you can see a console window in the background. The checkbox “Make Silent” (marked as 5) suppresses the background command window. The checkbox “Notify when closed” (Marked as 6) when checked, allows the application receiving the notification when process finished its operation.

3. Starting the Notepad Process

1) To create a process, we have to use Process class, which can be found in the System.Diagnostics namespace. Below is the using statement for it:

//Sample 01: Use Diagnostics namespace
using System.Diagnostics;

2) The "Start() Method" of the "Process Class" is used to spawn a process. In our case, we supply the document name to the Process start method when the path is given in the Document Path text box. Note that path validation is not done in the code, so when you are testing, provide a valid text document path.

//Sample 03: Start Notepad process. 
private void btnStartNotepad_Click(object sender, EventArgs e)
    if (txtDocPath.Text == String.Empty)
        Process.Start("Notepad.exe", txtDocPath.Text);

4. About the Batch File

This demo application starts the “copy.bat” batch file as a Process. The content of the copy.bat is shown below:

The batch file actually copies one or more files or directories from the specified source to the specified destination. Source and destination location can be passed as parameters to the batch file and these parameters will be substituted to %1 and %2 in the batch file. Out C# example application, passes these parameters as arguments to the Process and we will see that in the next session.

5. Running .Bat as C-Sharp Process

The code explanation below describes the how a batch file can be run as a Process:

1) First, the "Process Instance" is declared as a private data member of the class. The code is given below:

//Sample 02: Process for the batch
private Process BatchProc = null;

2) When source and destination path text boxes are empty, then we will not start the process and return from the “Start” button click event procedure. Note that validation for the proper path is not done and hence while executing the sample application, the valid path should be entered into the text boxes. The code is given below:

//4.1: Return when the strings are empty. However, path validation not done
if (txtSrcPath.Text == string.Empty || txtDestPath.Text == string.Empty)

3) The "ProcessStartInfo Class" will be useful to set information required to start the process. In our example, we created ProcInfo object of type "ProcessStartInfo" and specified the Copy.bat batch file name through its FileName parameter. Since path name is not specified, the “Copy.bat” should reside in the same folder where executable exists. Next, the arguments (i.e.) Source and destination file location for the copy operation is populated into the ProcInfo object through its member Arguments.

//4.2: Populate Process Information
ProcessStartInfo ProcInfo = new ProcessStartInfo();
ProcInfo.FileName = "Copy.bat";
ProcInfo.Arguments = "\"" + txtSrcPath.Text + "\" " + "\"" + txtDestPath.Text + "\"";

While forming the Argument note the usage of escape sequence \” to include the double quote as the path may contain spaces. The Parameter1 and parameter2 are separated by a space while forming the string for Argument member of the ProcessStartInfo class. The below picture shows how the string concatenation applied:

The yellow highlighted double quotes are required as some path may contain spaces. In the above picture D:\Temp does not have any space but the path in argument 1 is having the space. As the inputs are taken from the UI, it is advisable to use the escape sequence while forming Argument string. Parameter1 and parameter2 are separated by a blank space.

4) Once ProcessStartInfo structure is ready, we can pass that structure to the "Start() method" of the Process class. This is shown below:

//4.4: Start the Process and Hook-up process Exit Event
BatchProc = Process.Start(ProcInfo);

At this stage, the process will start spawning the Dos console window and executes the Copy.bat. The net effect is, the copy is performed based on the parameter specified in the text boxes.

6. Process – Suppress as Background Runnable

Sometimes we need to start a process in silent mode. That means, the application responsible for starting the process should not display any background window and the process task should go silent. Setting the "Hidden WindowStyle" to the ProcessStartInfo class can do this.  The code for starting the process silent is given below:

//4.3: Start the process in silent Mode3
if (chkBoxSilent.Checked == true)
    ProcInfo.WindowStyle = ProcessWindowStyle.Hidden;

7. Process Exit Notification

In some cases, we need to get a notification from the process stating that the task is completed or process exited. In our case, the process exits when the task of copying the file from source to destination is completed. The application starting the process can handle the "Exited Event" of the process to get the notification from the process. The code given below:

if (chkWhenClosed.Checked == true)
    BatchProc.EnableRaisingEvents = true;
    BatchProc.Exited += new System.EventHandler(Batch_Done);

The handler for the above exited event is shown below which displays a message box stating copy operation is completed:

//Sample 05: Handle Batch completed event
private void Batch_Done(object sender, EventArgs e)
    MessageBox.Show("Copy Completed!");
    BatchProc.Exited -= new System.EventHandler(Batch_Done);

The Entire application can be watched here

Source Code: Download

1 comment:

  1. Very informative :) keep it up!


Leave your comment(s) here.

Like this site? Tell it to your Firend :)