.NET
command line
process management
programming
software development

Execute multiple command lines with the same process using .NET

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

If you need to run several shell commands from a .NET program, starting a brand new process for every command is often unnecessary overhead. A more efficient pattern is to launch one persistent shell such as cmd.exe, PowerShell, or bash, redirect its standard input and output streams, and then feed multiple commands into the same running process.

The Core Pattern

The shell process stays alive while your .NET code writes commands into StandardInput. Output and errors are read back through the redirected streams.

csharp
1using System;
2using System.Diagnostics;
3
4class Program
5{
6    static void Main()
7    {
8        var process = new Process();
9        process.StartInfo.FileName = OperatingSystem.IsWindows() ? "cmd.exe" : "/bin/bash";
10        process.StartInfo.RedirectStandardInput = true;
11        process.StartInfo.RedirectStandardOutput = true;
12        process.StartInfo.RedirectStandardError = true;
13        process.StartInfo.UseShellExecute = false;
14        process.StartInfo.CreateNoWindow = true;
15
16        process.Start();
17
18        process.StandardInput.WriteLine("echo first command");
19        process.StandardInput.WriteLine("echo second command");
20        process.StandardInput.WriteLine("exit");
21
22        string output = process.StandardOutput.ReadToEnd();
23        string error = process.StandardError.ReadToEnd();
24
25        process.WaitForExit();
26
27        Console.WriteLine(output);
28        Console.WriteLine(error);
29    }
30}

This approach keeps one shell session alive long enough to execute several commands sequentially.

Why Use One Persistent Process

A persistent shell is useful when commands depend on shell state. For example, changing directory in one command should affect the next command, or an environment variable set early should still exist later in the same session.

That is difficult if every command is executed as a fresh child process, because each process starts from a clean context.

Using one shell also reduces startup overhead when you have many short commands.

Read Output Carefully

The simple example above is fine for small command sequences, but longer-running sessions often need asynchronous output reading. If the shell produces enough output and your program is not draining the redirected streams, the process can block.

That means persistent-shell orchestration is not just about writing commands. It is also about managing stdout, stderr, and session shutdown cleanly.

Choose The Right Shell

On Windows, cmd.exe works for basic commands, but PowerShell may be a better fit for script-heavy automation. On Linux or macOS, bash or sh is the usual choice.

The exact shell matters because quoting rules, built-in commands, variable syntax, and error semantics differ. A command sequence written for cmd.exe will not necessarily behave the same way in bash.

For more advanced scenarios, many tools add a sentinel marker after each command so the host application knows when one command finished and the next can start. Without some boundary protocol, a long-lived shell session can become hard to parse, especially when output from stderr and stdout interleaves.

Security also matters. If command strings contain untrusted input, a long-lived shell process can magnify the blast radius of injection mistakes because every subsequent command runs in the same shell context. Validate arguments carefully or prefer direct process execution when shell features are not actually required.

Common Pitfalls

One common mistake is forgetting that shell built-ins depend on the shell you launched. A command that works interactively in PowerShell may fail if the program actually started cmd.exe.

Another mistake is reading output only after all commands complete when the shell may emit enough data to fill buffers earlier. For larger workloads, read the streams asynchronously.

A third issue is leaving the shell open without sending exit or disposing the process. That can leak child processes and make the .NET program hang on shutdown.

Summary

  • To run multiple command lines in one .NET process, start a persistent shell and redirect standard input and output.
  • Write each command into StandardInput instead of creating a new child process every time.
  • This pattern is useful when commands share shell state such as working directory or environment variables.
  • Manage output streams and process shutdown carefully so the persistent shell does not block or leak.

Course illustration
Course illustration

All Rights Reserved.