Interacting with Windows Process Using C#

Introduction

 
Many Windows folks are aware of the Windows Task Manager, probably because of its popularity among Windows users. Moreover, developers have probably used it in some way or another to stop or end a program that appears to be in the “Process” tab. If you haven’t heard of or tried it, you can Google search it, or just press CTRL + SHIFT + ESC from your keyboard and it will appear.
 
Going back to our main goal in this article, we are going to explore the Windows process by answering the question of what it is, its role and how to interact with it via C# code samples.
 

What is a Windows Process?

 
Even before the .NET Framework came out, the concept of a “process” has existed since the early days of Windows OS. We can define a process as a running program that is being processed by the computer processor in an isolated manner. In addition, a process could be a background application that we don’t normally see running on our computer. A good example could be a printer driver program that runs in the background and watches the ink level attached to our computer. 
 

The Role of Windows Process

 
For instance, when a developer runs an executable(*.exe) program once it is loaded into memory, the operating system creates a separate and isolated process for its use during its lifetime. Then, several processes may be associated with the same program; for instance, opening 2 instances of notepad results in more than one process being executed. This approach is called, “application isolation” which results in a stable runtime environment and considering that the failure of one process does not affect the function of the other running processes.
 
Things to Remember When Dealing with Windows Processes
  • Every Windows process has a unique process identifier (PID)
  • It can be loaded and unloaded by the operating system as well as programmatically.
Getting started interacting with Windows Processes using C#
 

Enumerate Windows Processes

  1. [TestMethod]    
  2. public void Test_Enumerating_Running_Processes()    
  3. {    
  4.     string localMachineName = Environment.MachineName;    
  5.     
  6.     var runningProcess = Process.GetProcesses(localMachineName);    
  7.     
  8.     foreach (var process in runningProcess)    
  9.     {    
  10.         string processName = process.ProcessName;    
  11.         string processId = process.Id.ToString();    
  12.     
  13.         Console.WriteLine($"Process Id: {processId} Process Name: {processName}");    
  14.     
  15.         Assert.IsNotNull(processName);    
  16.     }    
  17. } 

Inspect a Specific Windows Process

  1. [TestMethod]    
  2. public void Test_Check_And_Inspect_A_Specific_Process()    
  3. {     
  4.     string localMachineName = Environment.MachineName;    
  5.     
  6.     var process = Process.GetProcesses(localMachineName)    
  7.                             .FirstOrDefault(p => p.ProcessName.Contains("chrome"));    
  8.     
  9.     if(process != null)    
  10.     {    
  11.         Assert.IsNotNull(process);    
  12.     }    
  13. } 

Investigate a Process’s Thread Details

  1. [TestMethod]    
  2. public void Test_Process_Thread_Set()    
  3. {    
  4.     string localMachineName = Environment.MachineName;    
  5.     
  6.     var process = Process.GetProcesses(localMachineName)    
  7.                             .FirstOrDefault(p => p.ProcessName.Contains("chrome"));    
  8.     
  9.     if (process != null)    
  10.     {    
  11.         foreach (ProcessThread thread in process.Threads)    
  12.         {    
  13.             string outputString = string.Empty;    
  14.     
  15.             outputString = $"Thread ID: {thread.Id} {Environment.NewLine}";    
  16.             outputString += $"Thread ID: {thread.StartTime.ToShortDateString()}";    
  17.             outputString += $"Priority: {thread.PriorityLevel}";    
  18.     
  19.             Console.WriteLine(outputString);    
  20.         }    
  21.     }    
  22.  

Investigate Process Module Details

  1. [TestMethod]    
  2. [ExpectedException(typeof(Win32Exception))]    
  3. public void Test_Process_Module_Set_Of_Details_1_Using_ProcessObject()    
  4. {    
  5.     string localMachineName = Environment.MachineName;    
  6.     
  7.     var process = Process.GetProcesses(localMachineName)    
  8.                             .FirstOrDefault(p => p.ProcessName.Contains("chrome"));    
  9.     
  10.     if (process != null)    
  11.     {    
  12.         foreach (ProcessModule module in process.Modules)    
  13.         {    
  14.             string outputString = string.Empty;    
  15.     
  16.             outputString = $"Module Name: {module.ModuleName} {Environment.NewLine}";    
  17.             outputString += $"Module Filename: {module.FileName}";    
  18.     
  19.             Console.WriteLine(outputString);    
  20.         }    
  21.     }    
  22. } 
The sample code above works well. However; there is one issue with this approach. When you are running this code in a 32bit mode, you'll be having an issue accessing the 64bit application paths. I do recommend to change your "Active solution platform" to x64. 
 

Investigate a Process’s Module Details II

 
Another example if you are having problems with your current platform.
  1. [TestMethod]    
  2. public void Test_Process_Module_Set_Of_Details_2_Using_ManagementObject()    
  3. {    
  4.     string localMachineName = Environment.MachineName;    
  5.     
  6.     var process = Process.GetProcesses(localMachineName)    
  7.                             .FirstOrDefault(p => p.ProcessName.Contains("chrome"));    
  8.     
  9.     if (process != null)    
  10.     {    
  11.         string query = $"SELECT ProcessId, ExecutablePath, CommandLine FROM Win32_Process WHERE ProcessId={process.Id}" ;    
  12.     
  13.         using(var search = new ManagementObjectSearcher(query))    
  14.         {    
  15.             using(var results = search.Get())    
  16.             {    
  17.     
  18.                 var processModuleDetails = results.Cast<ManagementObject>().FirstOrDefault();    
  19.     
  20.                 if (processModuleDetails != null)    
  21.                 {    
  22.                     var stringResult = $"Module Name: {processModuleDetails.GetPropertyValue("CommandLine")}{Environment.NewLine}";    
  23.                         stringResult += $"Module Filename:{processModuleDetails.GetPropertyValue("ExecutablePath")}{Environment.NewLine}";    
  24.                         stringResult += $"Process Id: {processModuleDetails.GetPropertyValue("ProcessId")}";    
  25.     
  26.     
  27.                     Console.WriteLine(stringResult);    
  28.                 }    
  29.             }    
  30.         }    
  31.     }    
  32. } 

Start and Stop/Kill Windows Process 

  1. [TestMethod]    
  2. public void Test_Process_Start_Process()    
  3. {    
  4.     string acrobatReaderName = "AcroRd32";    
  5.     
  6.     try    
  7.     {    
  8.         /*  
  9.          * For the complete argument list see the link below.  
  10.          * https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/pdf_open_parameters.pdf  
  11.          */    
  12.     
  13.         var acrobatReaderProcess = Process.Start(acrobatReaderName, "/n");    
  14.     }    
  15.     catch (InvalidOperationException ex)    
  16.     {    
  17.         Console.WriteLine(ex.Message);    
  18.     }    
  19. }     
  1. [TestMethod]    
  2. public void Test_Process_Stop_Process()    
  3. {    
  4.     string acrobatReaderName = "AcroRd32";    
  5.     
  6.     try    
  7.     {    
  8.         var acrobatReaderProcess = Process.GetProcessesByName(acrobatReaderName);    
  9.     
  10.         if (acrobatReaderProcess != null)    
  11.         {    
  12.             foreach (var item in acrobatReaderProcess)    
  13.             {    
  14.                 item.Kill();    
  15.     
  16.                 Console.WriteLine($"{item.ProcessName} has been killed!");  
  17.             }    
  18.         }    
  19.     }    
  20.     catch (Win32Exception ex)    
  21.     {    
  22.         Console.WriteLine(ex.Message);    
  23.     }    
  24. } 

Summary and Remarks

 
In this blog post, we have seen how to interact with the Windows processes using C#. To summarize the code sample, see the bulleted list below.
  • Enumerate Windows Processes
  • Inspect a Specific Process
  • Investigate a Process’s Thread Details
  • Investigate a Process’s Module Details
  • Start and Stop/Kill Process
I’m hoping with the help of these sample codes can get you started with it. You can download it here or you can go to GitHub. Lastly, I hope you have enjoyed this blog post until next time. Happy programming!