Logo

Operating Systems Lab - Week 5: Process Management in C#

19 min read
Lesson slides
1 / 15

Operating Systems Lab - Week 5: Process Management in C#

Launching, inspecting, and controlling external processes with System.Diagnostics

Table of Contents

  1. Introduction
  2. Getting Started with Processes
  3. Process Class Basics
  4. Process Methods Explained
  5. ProcessStartInfo - Advanced Configuration
  6. Cross-Platform Development
  7. Complete Working Examples
  8. Lab Exercises
  9. Quick Reference Guide

Introduction

What is a Process?

A process is a running instance of a program. When you double-click an application, the operating system creates a process for it.

Each process has:

  • Its own memory space (isolated from other processes)
  • Unique Process ID (PID)
  • Resources (files, network connections, etc.)
  • Execution state (running, waiting, etc.)

Example: When you open Notepad, the OS creates a "notepad.exe" process.

graph TD
    A[Your C# Application] -->|Process.Start| B[External Process]
    A -->|Monitor| C[Running Processes]
    A -->|Control| D[Process Lifecycle]
    B --> E[Operating System]
    C --> E
    D --> E
 
    style A fill:#4a90e2
    style E fill:#50c878

Why Learn Process Management?

Process management allows your C# applications to:

  • Launch other applications (open text editors, browsers, calculators)
  • Monitor system processes (track memory usage, CPU usage)
  • Control process lifecycle (start, stop, wait for processes)
  • Execute shell commands (run system commands programmatically)
  • Automate tasks (system administration, testing, deployment)

Real-World Uses:

  • System monitoring tools
  • Automated testing frameworks
  • Deployment scripts
  • Task automation
  • System administration utilities

Getting Started with Processes

Your First Process Program

Let's start with the simplest possible example:

Windows - Opening Notepad:

using System.Diagnostics;
 
class Program
{
    static void Main()
    {
        Process.Start("notepad.exe");
    }
}

Linux - Opening Text Editor:

using System.Diagnostics;
 
class Program
{
    static void Main()
    {
        Process.Start("xed");
    }
}

That's it! This single line tells the operating system to start a new process.


Opening a File with an Application

Windows:

using System.Diagnostics;
 
class Program
{
    static void Main()
    {
        Process.Start("notepad.exe", "example.txt");
    }
}

Linux:

using System.Diagnostics;
 
class Program
{
    static void Main()
    {
        Process.Start("xed", "example.txt");
    }
}

Getting Information About Your Process

Windows:

using System;
using System.Diagnostics;
 
class Program
{
    static void Main()
    {
        Process process = Process.Start("notepad.exe");
        
        Console.WriteLine($"Process Name: {process.ProcessName}");
        Console.WriteLine($"Process ID: {process.Id}");
        
        Console.WriteLine("\nPress Enter to close the program...");
        Console.ReadLine();
    }
}

Linux:

using System;
using System.Diagnostics;
 
class Program
{
    static void Main()
    {
        Process process = Process.Start("xed");
        
        Console.WriteLine($"Process Name: {process.ProcessName}");
        Console.WriteLine($"Process ID: {process.Id}");
        
        Console.WriteLine("\nPress Enter to close the program...");
        Console.ReadLine();
    }
}

Output Example (Windows):

Process Name: notepad
Process ID: 12345
 
Press Enter to close the program...

Output Example (Linux):

Process Name: xed
Process ID: 12345
 
Press Enter to close the program...

Process Class Basics

The System.Diagnostics Namespace

All process management functionality is in the System.Diagnostics namespace:

using System.Diagnostics;  // Always include this

Process Class Overview

classDiagram
    class Process {
        +ProcessName : string
        +Id : int
        +StartTime : DateTime
        +HasExited : bool
        +WorkingSet64 : long
        +Start() : Process
        +Kill() : void
        +WaitForExit() : void
        +Close() : void
    }
 
    class ProcessStartInfo {
        +FileName : string
        +Arguments : string
        +WorkingDirectory : string
        +UseShellExecute : bool
    }
 
    Process --> ProcessStartInfo : uses

Important Properties

PropertyTypeDescriptionExample
ProcessNamestringName of the process"notepad"
IdintUnique Process ID (PID)12345
StartTimeDateTimeWhen process started2025-11-03 10:30:00
HasExitedboolIs process still running?false
WorkingSet64longMemory usage (bytes)15728640

Example: Accessing Process Properties

Windows:

using System;
using System.Diagnostics;
 
class Program
{
    static void Main()
    {
        Process process = Process.Start("notepad.exe");
        
        Console.WriteLine("=== Process Information ===");
        Console.WriteLine($"Process Name: {process.ProcessName}");
        Console.WriteLine($"Process ID: {process.Id}");
        Console.WriteLine($"Start Time: {process.StartTime}");
        Console.WriteLine($"Memory (KB): {process.WorkingSet64 / 1024}");
        Console.WriteLine($"Has Exited: {process.HasExited}");
        
        Console.WriteLine("\nClose Notepad to continue...");
        process.WaitForExit();
        
        Console.WriteLine("\nNotepad has been closed!");
        Console.WriteLine($"Has Exited: {process.HasExited}");
    }
}

Linux:

using System;
using System.Diagnostics;
 
class Program
{
    static void Main()
    {
        Process process = Process.Start("xed");
        
        Console.WriteLine("=== Process Information ===");
        Console.WriteLine($"Process Name: {process.ProcessName}");
        Console.WriteLine($"Process ID: {process.Id}");
        Console.WriteLine($"Start Time: {process.StartTime}");
        Console.WriteLine($"Memory (KB): {process.WorkingSet64 / 1024}");
        Console.WriteLine($"Has Exited: {process.HasExited}");
        
        Console.WriteLine("\nClose xed to continue...");
        process.WaitForExit();
        
        Console.WriteLine("\nxed has been closed!");
        Console.WriteLine($"Has Exited: {process.HasExited}");
    }
}

Process Methods Explained

Information Retrieval Methods

graph LR
    A[Process Methods] --> B[GetProcesses]
    A --> C[GetCurrentProcess]
    A --> D[GetProcessesByName]
    A --> E[GetProcessById]
 
    B --> F[All Running Processes]
    C --> G[Your Application]
    D --> H[Find by Name]
    E --> I[Find by ID]
 
    style A fill:#4a90e2
    style F fill:#ffa500
    style G fill:#ffa500
    style H fill:#ffa500
    style I fill:#ffa500

1. GetProcesses() - List All Processes

Gets every process running on the system.

using System;
using System.Diagnostics;
 
class Program
{
    static void Main()
    {
        Process[] processes = Process.GetProcesses();
        
        Console.WriteLine($"Total processes: {processes.Length}\n");
        
        // Show first 10 processes
        for (int i = 0; i < 10 && i < processes.Length; i++)
        {
            Console.WriteLine($"{processes[i].ProcessName} (PID: {processes[i].Id})");
        }
    }
}

Output Example:

Total processes: 287
 
System (PID: 4)
svchost (PID: 756)
explorer (PID: 2184)
chrome (PID: 5432)
notepad (PID: 8912)
...

2. GetCurrentProcess() - Your Application

Gets the process for your own application.

using System;
using System.Diagnostics;
 
class Program
{
    static void Main()
    {
        Process me = Process.GetCurrentProcess();
        
        Console.WriteLine("=== My Process Info ===");
        Console.WriteLine($"Name: {me.ProcessName}");
        Console.WriteLine($"PID: {me.Id}");
        Console.WriteLine($"Memory: {me.WorkingSet64 / 1024} KB");
        Console.WriteLine($"Threads: {me.Threads.Count}");
    }
}

3. GetProcessesByName() - Find by Name

Find all processes with a specific name.

using System;
using System.Diagnostics;
 
class Program
{
    static void Main()
    {
        string name = "chrome";  // Process name to search
        Process[] processes = Process.GetProcessesByName(name);
        
        Console.WriteLine($"Found {processes.Length} instance(s) of {name}\n");
        
        foreach (Process p in processes)
        {
            double memoryMB = p.WorkingSet64 / (1024.0 * 1024.0);
            Console.WriteLine($"PID {p.Id}: {memoryMB:F2} MB");
        }
    }
}

Output Example:

Found 3 instance(s) of chrome
 
PID 5432: 125.34 MB
PID 6128: 89.21 MB
PID 7456: 112.67 MB

4. GetProcessById() - Find by Process ID

Find a specific process by its PID.

using System;
using System.Diagnostics;
 
class Program
{
    static void Main()
    {
        try
        {
            int pid = 1234;  // Replace with actual PID
            Process process = Process.GetProcessById(pid);
            
            Console.WriteLine($"Found process:");
            Console.WriteLine($"Name: {process.ProcessName}");
            Console.WriteLine($"ID: {process.Id}");
        }
        catch (ArgumentException)
        {
            Console.WriteLine("Process not found!");
        }
    }
}

Process Control Methods

graph TD
    A[Process Control] --> B[WaitForExit]
    A --> C[Kill]
    A --> D[Close]
 
    B --> E[Wait for natural exit]
    C --> F[Force terminate]
    D --> G[Release tracking]
 
    style A fill:#4a90e2
    style B fill:#50c878
    style C fill:#ff6b6b
    style D fill:#ffd93d

5. WaitForExit() - Wait for Process

Wait forever - Windows:

Process process = Process.Start("notepad.exe");
Console.WriteLine("Waiting for Notepad...");
process.WaitForExit();  // Blocks until Notepad closes
Console.WriteLine("Notepad closed!");

Wait forever - Linux:

Process process = Process.Start("xed");
Console.WriteLine("Waiting for xed...");
process.WaitForExit();  // Blocks until xed closes
Console.WriteLine("xed closed!");

Wait with timeout - Windows:

Process process = Process.Start("notepad.exe");
bool exited = process.WaitForExit(5000);  // Wait max 5 seconds
 
if (exited)
{
    Console.WriteLine("Process exited within 5 seconds");
}
else
{
    Console.WriteLine("Process still running after 5 seconds");
}

Wait with timeout - Linux:

Process process = Process.Start("xed");
bool exited = process.WaitForExit(5000);  // Wait max 5 seconds
 
if (exited)
{
    Console.WriteLine("Process exited within 5 seconds");
}
else
{
    Console.WriteLine("Process still running after 5 seconds");
}

6. Kill() - Force Terminate

⚠️ Warning: Kill() terminates immediately without cleanup!

Windows:

using System;
using System.Diagnostics;
using System.Threading;
 
class Program
{
    static void Main()
    {
        Process process = Process.Start("notepad.exe");
        
        Console.WriteLine("Notepad will be killed in 5 seconds...");
        Thread.Sleep(5000);
        
        process.Kill();
        process.WaitForExit();
        
        Console.WriteLine("Notepad terminated!");
    }
}

Linux:

using System;
using System.Diagnostics;
using System.Threading;
 
class Program
{
    static void Main()
    {
        Process process = Process.Start("xed");
        
        Console.WriteLine("xed will be killed in 5 seconds...");
        Thread.Sleep(5000);
        
        process.Kill();
        process.WaitForExit();
        
        Console.WriteLine("xed terminated!");
    }
}

7. Close() - Release Resources

Close() releases your tracking of the process, but the process keeps running.

Windows:

Process process = Process.Start("notepad.exe");
Console.WriteLine("Notepad started");
 
process.Close();  // Your app stops tracking it
Console.WriteLine("Tracking released (Notepad still running)");

Linux:

Process process = Process.Start("xed");
Console.WriteLine("xed started");
 
process.Close();  // Your app stops tracking it
Console.WriteLine("Tracking released (xed still running)");

Difference:

  • Kill(): Terminates the process ❌
  • Close(): Stops tracking the process, but it keeps running ✅

ProcessStartInfo - Advanced Configuration

What is ProcessStartInfo?

ProcessStartInfo gives you fine control over how a process starts.

Basic usage:

ProcessStartInfo startInfo = new ProcessStartInfo
{
    FileName = "notepad.exe",
    Arguments = "example.txt"
};
 
Process.Start(startInfo);

Key Properties

PropertyTypeDescription
FileNamestringProgram to run
ArgumentsstringCommand-line arguments
WorkingDirectorystringDirectory to run from
UseShellExecuteboolUse OS shell (true) or direct (false)
WindowStyleenumNormal, Maximized, Minimized, Hidden
CreateNoWindowboolDon't create console window
RedirectStandardOutputboolCapture output
RedirectStandardInputboolSend input
RedirectStandardErrorboolCapture errors

Example: Basic Configuration

Windows:

using System;
using System.Diagnostics;
 
class Program
{
    static void Main()
    {
        ProcessStartInfo startInfo = new ProcessStartInfo
        {
            FileName = "notepad.exe",
            Arguments = "example.txt",
            WindowStyle = ProcessWindowStyle.Maximized
        };
        
        Process.Start(startInfo);
        Console.WriteLine("Notepad opened (maximized)");
    }
}

Linux:

using System;
using System.Diagnostics;
 
class Program
{
    static void Main()
    {
        ProcessStartInfo startInfo = new ProcessStartInfo
        {
            FileName = "xed",
            Arguments = "example.txt",
            WindowStyle = ProcessWindowStyle.Maximized
        };
        
        Process.Start(startInfo);
        Console.WriteLine("xed opened (maximized)");
    }
}

Window Styles

graph LR
    A[WindowStyle] --> B[Normal]
    A --> C[Maximized]
    A --> D[Minimized]
    A --> E[Hidden]
 
    B --> F[Default size]
    C --> G[Fullscreen]
    D --> H[Taskbar only]
    E --> I[No window]
 
    style A fill:#4a90e2

Example:

Windows:

// Normal window
new ProcessStartInfo { FileName = "notepad.exe", WindowStyle = ProcessWindowStyle.Normal };
 
// Maximized window
new ProcessStartInfo { FileName = "notepad.exe", WindowStyle = ProcessWindowStyle.Maximized };
 
// Minimized window
new ProcessStartInfo { FileName = "notepad.exe", WindowStyle = ProcessWindowStyle.Minimized };
 
// Hidden window
new ProcessStartInfo { FileName = "notepad.exe", WindowStyle = ProcessWindowStyle.Hidden };

Linux:

// Normal window
new ProcessStartInfo { FileName = "xed", WindowStyle = ProcessWindowStyle.Normal };
 
// Maximized window
new ProcessStartInfo { FileName = "xed", WindowStyle = ProcessWindowStyle.Maximized };
 
// Minimized window
new ProcessStartInfo { FileName = "xed", WindowStyle = ProcessWindowStyle.Minimized };
 
// Hidden window
new ProcessStartInfo { FileName = "xed", WindowStyle = ProcessWindowStyle.Hidden };

UseShellExecute Explained

This property is very important for understanding how processes start.

UseShellExecute = true (default):

  • ✅ Can open URLs (https://google.com)
  • ✅ Can open documents with default programs
  • ❌ Cannot redirect input/output

UseShellExecute = false:

  • ✅ Can redirect input/output
  • ✅ Direct program execution
  • ❌ Cannot open URLs directly

Example - Opening URL (requires true):

ProcessStartInfo startInfo = new ProcessStartInfo
{
    FileName = "https://www.google.com",
    UseShellExecute = true  // Required for URLs
};
Process.Start(startInfo);

Capturing Command Output

To capture output, you must:

  1. Set UseShellExecute = false
  2. Set RedirectStandardOutput = true

Windows Example:

using System;
using System.Diagnostics;
 
class Program
{
    static void Main()
    {
        ProcessStartInfo startInfo = new ProcessStartInfo
        {
            FileName = "cmd.exe",
            Arguments = "/c date /t",  // Get current date
            UseShellExecute = false,
            RedirectStandardOutput = true,
            CreateNoWindow = true
        };
        
        Process process = Process.Start(startInfo);
        string output = process.StandardOutput.ReadToEnd();
        process.WaitForExit();
        
        Console.WriteLine("Command output:");
        Console.WriteLine(output);
    }
}

Linux Example:

using System;
using System.Diagnostics;
 
class Program
{
    static void Main()
    {
        ProcessStartInfo startInfo = new ProcessStartInfo
        {
            FileName = "/bin/bash",
            Arguments = "-c \"date\"",  // Get current date
            UseShellExecute = false,
            RedirectStandardOutput = true,
            CreateNoWindow = true
        };
        
        Process process = Process.Start(startInfo);
        string output = process.StandardOutput.ReadToEnd();
        process.WaitForExit();
        
        Console.WriteLine("Command output:");
        Console.WriteLine(output);
    }
}

Redirecting Input, Output, and Errors

sequenceDiagram
    participant App as Your Application
    participant Proc as External Process
    participant OS as Operating System
 
    App->>Proc: Start with Redirect = true
    App->>Proc: Send commands (StandardInput)
    Proc->>OS: Execute commands
    OS->>Proc: Return output
    Proc->>App: Output (StandardOutput)
    Proc->>App: Errors (StandardError)

Complete Example:

using System;
using System.Diagnostics;
 
class Program
{
    static void Main()
    {
        ProcessStartInfo startInfo = new ProcessStartInfo
        {
            FileName = "cmd.exe",  // Windows
            UseShellExecute = false,
            RedirectStandardInput = true,
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            CreateNoWindow = true
        };
        
        Process process = Process.Start(startInfo);
        
        // Send commands
        process.StandardInput.WriteLine("echo Hello World!");
        process.StandardInput.WriteLine("date /t");
        process.StandardInput.WriteLine("exit");
        
        // Read output
        string output = process.StandardOutput.ReadToEnd();
        string errors = process.StandardError.ReadToEnd();
        
        process.WaitForExit();
        
        Console.WriteLine("=== Output ===");
        Console.WriteLine(output);
        
        if (!string.IsNullOrEmpty(errors))
        {
            Console.WriteLine("\n=== Errors ===");
            Console.WriteLine(errors);
        }
    }
}

Cross-Platform Development

Detecting the Operating System

using System;
using System.Runtime.InteropServices;
 
class Program
{
    static void Main()
    {
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
        {
            Console.WriteLine("Running on Windows");
        }
        else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
        {
            Console.WriteLine("Running on Linux");
        }
        else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
        {
            Console.WriteLine("Running on macOS");
        }
    }
}

Platform Differences

TaskWindowsLinux
Text Editornotepad.exexed, nano, vim
Shellcmd.exe, powershell.exe/bin/bash
Shell Flag/c-c
Browserchrome.exegoogle-chrome, firefox
File Managerexplorer.exenautilus

Example: Cross-Platform Text Editor

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
 
class Program
{
    static void Main()
    {
        OpenTextEditor("example.txt");
    }
    
    static void OpenTextEditor(string fileName)
    {
        ProcessStartInfo startInfo = new ProcessStartInfo();
        
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
        {
            startInfo.FileName = "notepad.exe";
            startInfo.Arguments = fileName;
        }
        else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
        {
            startInfo.FileName = "xed";
            startInfo.Arguments = fileName;
        }
        else
        {
            Console.WriteLine("Unsupported OS");
            return;
        }
        
        try
        {
            Process.Start(startInfo);
            Console.WriteLine($"Opened: {fileName}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }
    }
}

Example: Cross-Platform Browser

using System;
using System.Diagnostics;
 
class Program
{
    static void Main()
    {
        OpenBrowser("https://www.google.com");
    }
    
    static void OpenBrowser(string url)
    {
        try
        {
            ProcessStartInfo startInfo = new ProcessStartInfo
            {
                FileName = url,
                UseShellExecute = true
            };
            
            Process.Start(startInfo);
            Console.WriteLine($"Opened: {url}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }
    }
}

Example: Cross-Platform Shell Commands

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
 
class Program
{
    static void Main()
    {
        string output = ExecuteCommand("echo Hello World!");
        Console.WriteLine(output);
    }
    
    static string ExecuteCommand(string command)
    {
        ProcessStartInfo startInfo = new ProcessStartInfo();
        
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
        {
            startInfo.FileName = "cmd.exe";
            startInfo.Arguments = $"/c {command}";
        }
        else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
        {
            startInfo.FileName = "/bin/bash";
            startInfo.Arguments = $"-c \"{command}\"";
        }
        else
        {
            return "Unsupported OS";
        }
        
        startInfo.UseShellExecute = false;
        startInfo.RedirectStandardOutput = true;
        startInfo.CreateNoWindow = true;
        
        try
        {
            Process process = Process.Start(startInfo);
            string output = process.StandardOutput.ReadToEnd();
            process.WaitForExit();
            return output;
        }
        catch (Exception ex)
        {
            return $"Error: {ex.Message}";
        }
    }
}

Complete Working Examples

Example 1: Process Monitor

Monitor system processes and show top memory users.

using System;
using System.Diagnostics;
using System.Linq;
 
class Program
{
    static void Main()
    {
        Console.WriteLine("=== PROCESS MONITOR ===\n");
        
        Process[] processes = Process.GetProcesses();
        
        var topProcesses = processes
            .OrderByDescending(p => p.WorkingSet64)
            .Take(10);
        
        Console.WriteLine("Top 10 processes by memory:\n");
        Console.WriteLine("{0,-30} {1,-10} {2,15}", "Name", "PID", "Memory (MB)");
        Console.WriteLine(new string('-', 60));
        
        foreach (var p in topProcesses)
        {
            try
            {
                double mb = p.WorkingSet64 / (1024.0 * 1024.0);
                Console.WriteLine("{0,-30} {1,-10} {2,15:F2}", 
                    p.ProcessName, p.Id, mb);
            }
            catch { }
        }
    }
}

Example 2: Process Search Tool

using System;
using System.Diagnostics;
 
class Program
{
    static void Main()
    {
        Console.Write("Enter process name to search: ");
        string name = Console.ReadLine();
        
        Process[] processes = Process.GetProcessesByName(name);
        
        if (processes.Length == 0)
        {
            Console.WriteLine($"\nNo processes found: {name}");
            return;
        }
        
        Console.WriteLine($"\nFound {processes.Length} process(es):\n");
        Console.WriteLine("{0,-10} {1,15} {2,20}", "PID", "Memory (MB)", "Start Time");
        Console.WriteLine(new string('-', 50));
        
        foreach (var p in processes)
        {
            try
            {
                double mb = p.WorkingSet64 / (1024.0 * 1024.0);
                Console.WriteLine("{0,-10} {1,15:F2} {2,20}",
                    p.Id, mb, p.StartTime.ToString("HH:mm:ss"));
            }
            catch { }
        }
    }
}

Example 3: Process Instance Manager

Limit your application to 3 running instances.

using System;
using System.Diagnostics;
 
class Program
{
    static void Main()
    {
        Process current = Process.GetCurrentProcess();
        Process[] instances = Process.GetProcessesByName(current.ProcessName);
        
        Console.WriteLine($"=== INSTANCE MANAGER ===");
        Console.WriteLine($"Running instances: {instances.Length}\n");
        
        // Show all instances
        foreach (var inst in instances)
        {
            string marker = inst.Id == current.Id ? " (This one)" : "";
            Console.WriteLine($"PID: {inst.Id}{marker}");
        }
        
        // Check limit
        if (instances.Length < 3)
        {
            Console.Write("\nStart new instance? (y/n): ");
            if (Console.ReadLine()?.ToLower() == "y")
            {
                ProcessStartInfo startInfo = new ProcessStartInfo
                {
                    FileName = Environment.ProcessPath,
                    UseShellExecute = true
                };
                Process.Start(startInfo);
                Console.WriteLine("New instance started!");
            }
        }
        else
        {
            Console.WriteLine("\nMaximum instances (3) reached!");
        }
        
        Console.WriteLine("\nPress Enter to exit...");
        Console.ReadLine();
    }
}

Example 4: Interactive Command Executor

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
 
class Program
{
    static void Main()
    {
        Console.WriteLine("=== COMMAND EXECUTOR ===");
        Console.WriteLine("Type commands (or 'exit' to quit)\n");
        
        while (true)
        {
            Console.Write("> ");
            string command = Console.ReadLine();
            
            if (command?.ToLower() == "exit")
                break;
            
            if (string.IsNullOrWhiteSpace(command))
                continue;
            
            string output = ExecuteCommand(command);
            Console.WriteLine(output);
        }
    }
    
    static string ExecuteCommand(string command)
    {
        ProcessStartInfo startInfo = new ProcessStartInfo();
        
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
        {
            startInfo.FileName = "cmd.exe";
            startInfo.Arguments = $"/c {command}";
        }
        else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
        {
            startInfo.FileName = "/bin/bash";
            startInfo.Arguments = $"-c \"{command}\"";
        }
        else
        {
            return "Unsupported OS";
        }
        
        startInfo.UseShellExecute = false;
        startInfo.RedirectStandardOutput = true;
        startInfo.RedirectStandardError = true;
        startInfo.CreateNoWindow = true;
        
        try
        {
            Process process = Process.Start(startInfo);
            string output = process.StandardOutput.ReadToEnd();
            string errors = process.StandardError.ReadToEnd();
            process.WaitForExit();
            
            return string.IsNullOrEmpty(errors) ? output : $"{output}\nErrors:\n{errors}";
        }
        catch (Exception ex)
        {
            return $"Error: {ex.Message}";
        }
    }
}

Lab Exercises

Exercise 1: Simple Process Launcher ⭐

Objective: Create a cross-platform text editor launcher.

Requirements:

  1. Detect the operating system
  2. Launch appropriate text editor (notepad.exe or xed)
  3. Open file "lab5_output.txt"
  4. Display success message

Hints:

  • Use RuntimeInformation.IsOSPlatform()
  • Use try-catch for error handling
  • Refer to "Cross-Platform Text Editor" example

Expected Output:

Operating System: Linux
Opening text editor...
Opened: lab5_output.txt

Exercise 2: Process Monitor ⭐⭐

Objective: Create a process monitoring application.

Requirements:

  1. List all running processes
  2. Display: Name, PID, Memory (MB)
  3. Allow user to search by name
  4. Show top 5 by memory usage

Hints:

  • Use Process.GetProcesses()
  • Use LINQ .OrderByDescending(p => p.WorkingSet64)
  • Format: WorkingSet64 / (1024.0 * 1024.0)

Sample Menu:

=== PROCESS MONITOR ===
1. List all processes
2. Search by name
3. Top 5 by memory
0. Exit
 
Choice:

Exercise 3: Shell Command Executor ⭐⭐

Objective: Build cross-platform command executor.

Requirements:

  1. Accept user commands
  2. Execute on correct shell
  3. Display output
  4. Handle errors

Test Commands:

  • Windows: dir, echo Hello, date /t
  • Linux: ls -la, echo Hello, pwd

Hints:

  • Set UseShellExecute = false
  • Set RedirectStandardOutput = true
  • Capture both output and errors

Exercise 4: Process Control ⭐⭐⭐

Objective: Demonstrate WaitForExit, Kill, Close.

Requirements:

  1. Start text editor
  2. Show process info
  3. Menu options:
    • Wait for exit
    • Kill after 10 seconds
    • Close tracking
  4. Show appropriate messages

Hints:

  • Use Thread.Sleep(10000)
  • Check HasExited before operations
  • Explain difference between Kill and Close

Exercise 5: Instance Manager ⭐⭐⭐

Objective: Limit to 3 running instances.

Requirements:

  1. Count running instances
  2. Display each PID
  3. Allow starting new instance (if < 3)
  4. Block if limit reached

Challenge: Add kill-by-PID feature.

Hints:

  • Use Process.GetCurrentProcess()
  • Use Process.GetProcessesByName()
  • Use Environment.ProcessPath

Quick Reference Guide

Common Process Operations

Start a process:

Windows:

Process.Start("notepad.exe");
Process.Start("notepad.exe", "file.txt");

Linux:

Process.Start("xed");
Process.Start("xed", "file.txt");

Get process info:

Windows:

Process p = Process.Start("notepad.exe");
Console.WriteLine($"{p.ProcessName} - PID: {p.Id}");

Linux:

Process p = Process.Start("xed");
Console.WriteLine($"{p.ProcessName} - PID: {p.Id}");

Wait for exit:

process.WaitForExit();                    // Wait forever
bool exited = process.WaitForExit(5000);  // 5 second timeout

Kill process:

Windows:

process.Kill();
process.WaitForExit();

Linux:

process.Kill();
process.WaitForExit();

(Same for both platforms)

List all processes:

Process[] all = Process.GetProcesses();

Find by name:

Process[] chrome = Process.GetProcessesByName("chrome");

Current process:

Process me = Process.GetCurrentProcess();

Capturing Command Output

Windows:

ProcessStartInfo startInfo = new ProcessStartInfo
{
    FileName = "cmd.exe",
    Arguments = "/c dir",
    UseShellExecute = false,
    RedirectStandardOutput = true
};
 
Process p = Process.Start(startInfo);
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();

Linux:

ProcessStartInfo startInfo = new ProcessStartInfo
{
    FileName = "/bin/bash",
    Arguments = "-c \"ls -la\"",
    UseShellExecute = false,
    RedirectStandardOutput = true
};
 
Process p = Process.Start(startInfo);
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();

Platform Detection

using System.Runtime.InteropServices;
 
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
    // Windows code
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
    // Linux code
}

Quick Copy-Paste Examples

List all processes:

using System;
using System.Diagnostics;
 
class Program
{
    static void Main()
    {
        foreach (var p in Process.GetProcesses())
        {
            Console.WriteLine($"{p.ProcessName} - {p.Id}");
        }
    }
}

Top 5 by memory:

using System;
using System.Diagnostics;
using System.Linq;
 
class Program
{
    static void Main()
    {
        var top = Process.GetProcesses()
            .OrderByDescending(p => p.WorkingSet64)
            .Take(5);
        
        foreach (var p in top)
        {
            double mb = p.WorkingSet64 / (1024.0 * 1024.0);
            Console.WriteLine($"{p.ProcessName}: {mb:F2} MB");
        }
    }
}

Get current process:

using System;
using System.Diagnostics;
 
class Program
{
    static void Main()
    {
        Process me = Process.GetCurrentProcess();
        Console.WriteLine($"Name: {me.ProcessName}");
        Console.WriteLine($"PID: {me.Id}");
        Console.WriteLine($"Memory: {me.WorkingSet64 / 1024} KB");
    }
}

Search processes:

using System;
using System.Diagnostics;
 
class Program
{
    static void Main()
    {
        Process[] procs = Process.GetProcessesByName("chrome");
        Console.WriteLine($"Found {procs.Length} instances");
        
        foreach (var p in procs)
        {
            Console.WriteLine($"PID: {p.Id}");
        }
    }
}

Kill after timeout:

Windows:

using System;
using System.Diagnostics;
using System.Threading;
 
class Program
{
    static void Main()
    {
        Process p = Process.Start("notepad.exe");
        Console.WriteLine("Killing in 5 seconds...");
        Thread.Sleep(5000);
        p.Kill();
        p.WaitForExit();
        Console.WriteLine("Killed!");
    }
}

Linux:

using System;
using System.Diagnostics;
using System.Threading;
 
class Program
{
    static void Main()
    {
        Process p = Process.Start("xed");
        Console.WriteLine("Killing in 5 seconds...");
        Thread.Sleep(5000);
        p.Kill();
        p.WaitForExit();
        Console.WriteLine("Killed!");
    }
}

Useful Commands for Lab

Windows:

dotnet build
dotnet run
tasklist
taskkill /PID 1234

Linux:

dotnet build
dotnet run
ps aux
ps aux | grep processname
kill 1234
pkill processname
top

Best Practices

Always:

  • Use try-catch for process operations
  • Call Dispose() or use using statements
  • Check HasExited before accessing properties
  • Use platform detection for cross-platform code

⚠️ Be Careful:

  • Kill() terminates without cleanup
  • Some processes need elevated privileges
  • Process names are case-sensitive on Linux

Never:

  • Execute untrusted user input
  • Forget to wait after Kill()
  • Ignore exceptions

Summary

What You Learned

Process Basics: Understanding what processes are
Process Class: Properties and methods
Starting Processes: Simple and advanced ways
Process Information: Getting and monitoring
Process Control: Wait, Kill, Close
ProcessStartInfo: Advanced configuration
I/O Redirection: Capturing output
Cross-Platform: Windows and Linux support

mindmap
  root((Process Management))
    Basics
      What is a Process
      Process.Start
      Properties
    Methods
      GetProcesses
      GetCurrentProcess
      GetProcessesByName
      GetProcessById
    Control
      WaitForExit
      Kill
      Close
    Advanced
      ProcessStartInfo
      I/O Redirection
      Cross-Platform

Key Takeaways

  1. Processes are programs running on your computer
  2. C# System.Diagnostics provides powerful process tools
  3. Always handle errors with try-catch
  4. Cross-platform code needs OS detection
  5. Kill() is dangerous - use carefully