C#
run EXE
process start
programming
coding tips

How can I run an EXE file from my C code?

Master System Design with Codemia

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

Introduction

Running an external .exe from C# is a standard .NET task for launching tools, installers, converters, or background utilities. The correct API is System.Diagnostics.Process, usually configured through ProcessStartInfo. The important design choices are whether you need to wait for the process, capture its output, pass arguments safely, and avoid shell-related surprises.

Start a Process with ProcessStartInfo

For a basic launch, create a ProcessStartInfo, set the executable path, and start the process.

csharp
1using System;
2using System.Diagnostics;
3
4var startInfo = new ProcessStartInfo
5{
6    FileName = @"C:\Tools\DemoApp.exe",
7    UseShellExecute = true
8};
9
10Process.Start(startInfo);
11Console.WriteLine("Process started.");

UseShellExecute = true is useful when you want Windows shell behavior such as opening a document with its associated application. For direct program execution with redirected output, set it to false.

Pass Arguments Safely

If the executable needs arguments, pass them through ArgumentList on modern .NET or through Arguments on older setups.

csharp
1using System;
2using System.Diagnostics;
3
4var startInfo = new ProcessStartInfo
5{
6    FileName = @"C:\Tools\ImageTool.exe",
7    UseShellExecute = false
8};
9
10startInfo.ArgumentList.Add("--input");
11startInfo.ArgumentList.Add(@"C:\Data\photo.png");
12startInfo.ArgumentList.Add("--quality");
13startInfo.ArgumentList.Add("90");
14
15using var process = Process.Start(startInfo);
16process.WaitForExit();
17
18Console.WriteLine($"Exit code: {process.ExitCode}");

ArgumentList is safer than manually concatenating one long string because it avoids quoting mistakes for paths with spaces.

Capture Standard Output and Error

If you need the external program's output, disable shell execution and redirect streams explicitly.

csharp
1using System;
2using System.Diagnostics;
3using System.Threading.Tasks;
4
5static async Task<int> RunToolAsync()
6{
7    var startInfo = new ProcessStartInfo
8    {
9        FileName = "cmd.exe",
10        UseShellExecute = false,
11        RedirectStandardOutput = true,
12        RedirectStandardError = true
13    };
14
15    startInfo.ArgumentList.Add("/c");
16    startInfo.ArgumentList.Add("echo hello from child process");
17
18    using var process = new Process { StartInfo = startInfo };
19    process.Start();
20
21    string stdout = await process.StandardOutput.ReadToEndAsync();
22    string stderr = await process.StandardError.ReadToEndAsync();
23    await process.WaitForExitAsync();
24
25    Console.WriteLine(stdout.Trim());
26    Console.WriteLine($"stderr: {stderr.Trim()}");
27
28    return process.ExitCode;
29}

Capturing output is essential when the child process is part of a build, validation, or automation pipeline.

Wait, Timeout, and Exit Codes

Sometimes you only need to start the program and move on. Other times you must block until it finishes and check the result.

csharp
1using System;
2using System.Diagnostics;
3
4var startInfo = new ProcessStartInfo
5{
6    FileName = @"C:\Tools\DemoApp.exe",
7    UseShellExecute = false
8};
9
10using var process = Process.Start(startInfo);
11
12if (!process.WaitForExit(5000))
13{
14    process.Kill(entireProcessTree: true);
15    throw new TimeoutException("External tool did not finish in time.");
16}
17
18Console.WriteLine($"Exit code: {process.ExitCode}");

Timeout handling matters in services and background jobs. Without it, one hung external process can stall the whole application.

Set Working Directory and Environment Variables

Many executables assume a specific working directory or environment. Set those explicitly instead of relying on the parent process state.

csharp
1using System.Diagnostics;
2
3var startInfo = new ProcessStartInfo
4{
5    FileName = @"C:\Tools\Worker.exe",
6    WorkingDirectory = @"C:\Tools",
7    UseShellExecute = false
8};
9
10startInfo.Environment["APP_MODE"] = "batch";
11
12using var process = Process.Start(startInfo);
13process.WaitForExit();

This makes the execution environment reproducible, which is especially important in services, scheduled tasks, and CI agents.

Security and Reliability Notes

Launching executables is a trust boundary. Do not pass unvalidated user input into executable paths or arguments. Also avoid assuming that a missing process will fail clearly; check for file existence if the path comes from configuration.

If the external tool is central to your app's logic, log the start command, exit code, and stderr output. Those details matter when operators need to debug failures later.

Common Pitfalls

  • Building a single argument string by hand and getting quoting wrong for paths with spaces.
  • Using shell execution when you actually need redirected output or precise process control.
  • Waiting forever for a child process that may hang or display a hidden prompt.
  • Assuming the current working directory is what the child process expects.
  • Passing untrusted input directly into executable paths or arguments.

Summary

  • Use ProcessStartInfo and Process.Start to run an .exe from C#.
  • Prefer ArgumentList when you need to pass arguments safely.
  • Disable shell execution when you need stdout, stderr, or strict process control.
  • Add timeout and exit-code handling for automation and service code.
  • Treat external process execution as an operational and security boundary, not just a code detail.

Course illustration
Course illustration

All Rights Reserved.