C# コマンド入門:実行方法・外部コマンド呼び出し・よくあるエラーを初心者向けに解説

はじめに

C#を学び始めると、「C# コマンド」「C#をコマンドで実行する」「C#から外部コマンドを呼び出す」といった表現をよく見かけます。

しかし、ここでいう「コマンド」は文脈によって意味が変わります。たとえば、C#プログラムを実行するためのdotnet runもコマンドですし、C#プログラムの中からdirpingなどを実行することも「コマンド実行」と呼ばれます。

この記事では、初心者向けにC#のコマンドに関する基本を整理しながら、次の内容を解説します。

C#プログラムをコマンドで作成・ビルド・実行する方法、コマンドライン引数を受け取る方法、C#から外部コマンドを呼び出す方法、よくあるエラーと解決方法、安全にコマンドを実行するための注意点まで、実用的なサンプルを交えて紹介します。

1. C#の「コマンド」とは?初心者が混同しやすい意味を整理

C#における「コマンド」という言葉は、ひとつの意味だけで使われているわけではありません。

初心者が混乱しやすい理由は、「C#を実行するためのコマンド」と「C#から実行する外部コマンド」が同じように説明されることがあるためです。

まずは、C#でよく使われる「コマンド」の意味を整理しましょう。

1-1. C#で使われる「コマンド」の主な意味

C#で「コマンド」と言う場合、主に次のような意味があります。

意味
C#プロジェクトを操作するコマンドdotnet newdotnet builddotnet run
C#プログラムを実行するときのコマンドdotnet runMyApp.exe
C#から外部プログラムを呼び出す処理Process.Start()
WindowsやLinuxのOSコマンドdirlspingcopy
プログラムに渡す引数dotnet run -- name age

つまり、「C# コマンド」と検索して出てくる情報には、複数のテーマが含まれています。

1-2. C#プログラムの実行コマンドとは

C#プログラムをコマンドで実行する場合、現在よく使われるのは.NET CLIdotnetコマンドです。

たとえば、C#のコンソールアプリを実行するには、次のように入力します。

Bash
dotnet run

dotnetコマンドは、.NETプロジェクトを操作するためのコマンドであり、アプリケーションを実行するためにも使われます。公式ドキュメントでも、dotnetコマンドは.NETプロジェクトを操作する機能と、.NETアプリケーションを実行する機能を持つと説明されています。

1-3. 外部コマンド呼び出しとは

外部コマンド呼び出しとは、C#プログラムの中から別のプログラムやOSコマンドを実行することです。

たとえば、C#からWindowsのpingコマンドを実行したり、バッチファイルを実行したり、外部のexeファイルを起動したりできます。

C#では、主にSystem.Diagnostics.Processクラスを使って外部コマンドを実行します。

C#
using System.Diagnostics;

Process.Start("notepad.exe");

この例では、C#からメモ帳を起動しています。

1-4. コマンドライン引数とは

コマンドライン引数とは、プログラムを実行するときに外部から渡す値のことです。

たとえば、次のように実行したとします。

Bash
dotnet run -- Taro 25

この場合、Taro25がC#プログラムに渡される引数です。

C#側では、Mainメソッドのargsで受け取れます。

C#
static void Main(string[] args)
{
Console.WriteLine(args[0]);
Console.WriteLine(args[1]);
}

コマンドライン引数を使うと、実行時にファイル名、モード、ユーザー名、設定値などを指定できるようになります。

1-5. この記事で解説する範囲

この記事では、C#のコマンドについて次の範囲を扱います。

C#プログラムをコマンドで作成・ビルド・実行する方法、C#でコマンドライン引数を受け取る方法、C#から外部コマンドを実行する方法、実行結果やエラー出力を取得する方法、よくあるトラブルの解決方法、安全にコマンドを扱うための注意点を解説します。

一方で、ASP.NET Coreのデプロイコマンドや、Azure CLIなどのクラウド系コマンドはこの記事の主な対象外です。

2. C#プログラムをコマンドで実行する基本手順

まずは、C#プログラムをコマンドで実行する基本的な流れを確認しましょう。

ここでは、.NET SDKがインストールされている環境を前提に説明します。

2-1. C#をコマンドで実行するために必要な環境

C#をコマンドで実行するには、基本的に次の環境が必要です。

必要なもの説明
.NET SDKC#のビルドや実行に必要
ターミナルWindowsならコマンドプロンプト、PowerShell、Windows Terminalなど
エディタVisual Studio Code、Visual Studio、メモ帳など

インストール後、ターミナルで次のコマンドを実行して確認します。

Bash
dotnet --version

バージョン番号が表示されれば、dotnetコマンドを使用できます。

Bash
8.0.100

表示されるバージョンは環境によって異なります。

2-2. dotnetコマンドの基本

dotnetコマンドは、C#を含む.NETアプリケーションの作成、復元、ビルド、実行、公開などに使います。

よく使うコマンドは次のとおりです。

Bash
dotnet --version
dotnet new console
dotnet build
dotnet run
dotnet publish

それぞれの役割は次のようになります。

コマンド役割
dotnet --versionインストールされている.NET SDKのバージョンを確認
dotnet new consoleコンソールアプリのプロジェクトを作成
dotnet buildプログラムをビルド
dotnet runプログラムを実行
dotnet publish配布用ファイルを作成

初心者のうちは、まずdotnet new consoledotnet builddotnet runの3つを覚えれば十分です。

2-3. 新しいC#プロジェクトを作成する方法

新しいC#のコンソールアプリを作成するには、次のコマンドを使います。

Bash
dotnet new console -n CSharpCommandSample

-nはプロジェクト名を指定するオプションです。

このコマンドを実行すると、CSharpCommandSampleというフォルダが作成され、その中にC#のプロジェクトファイルやソースコードが生成されます。

Bash
cd CSharpCommandSample

フォルダに移動したら、C#プログラムを編集・実行できる状態になります。

dotnet newコマンドは、指定したテンプレートに基づいて.NETプロジェクトやファイルを作成するコマンドです。公式ドキュメントでも、dotnet newはテンプレートに基づいて成果物を作成すると説明されています。

2-4. C#プログラムをビルドする方法

C#プログラムをビルドするには、プロジェクトフォルダで次のコマンドを実行します。

Bash
dotnet build

ビルドとは、C#のソースコードをコンピューターが実行できる形に変換する作業です。

成功すると、次のようなメッセージが表示されます。

Bash
Build succeeded.
0 Warning(s)
0 Error(s)

エラーがある場合は、ファイル名、行番号、エラー内容が表示されます。

たとえば、セミコロンが抜けている場合は、コンパイルエラーが表示されます。

C#
Console.WriteLine("Hello")

このようなコードでは、末尾の;がないためエラーになります。

正しくは次のように書きます。

C#
Console.WriteLine("Hello");

2-5. C#プログラムを実行する方法

C#プログラムを実行するには、次のコマンドを使います。

Bash
dotnet run

初期状態のコンソールアプリであれば、次のような結果が表示されます。

Bash
Hello, World!

dotnet runは、ソースコードからアプリケーションを実行するための便利なコマンドです。公式ドキュメントでは、dotnet runは内部的にdotnet buildに依存してコードをビルドすると説明されています。

つまり、開発中は次のように覚えるとわかりやすいです。

Bash
dotnet run

これは「ビルドしてから実行する」ためのコマンドです。

2-6. 実行結果を確認する方法

実行結果は、ターミナル上に表示されます。

たとえば、Program.csを次のように変更します。

C#
Console.WriteLine("C# コマンドの練習です");
Console.WriteLine(DateTime.Now);

次に実行します。

Bash
dotnet run

実行結果は次のようになります。

Bash
C# コマンドの練習です
2026/06/07 10:30:00

日時は実行した環境によって変わります。

C#の学習では、まずConsole.WriteLine()で値を表示しながら動作確認するのが基本です。

3. C#でコマンドライン引数を受け取る方法

次に、C#プログラムでコマンドライン引数を受け取る方法を解説します。

コマンドライン引数を使うと、実行時に値を渡せるため、プログラムを柔軟に動かせます。

3-1. Mainメソッドとargsの基本

C#のコンソールアプリでは、Mainメソッドの引数としてstring[] argsを使えます。

C#
class Program
{
static void Main(string[] args)
{
Console.WriteLine("引数の数: " + args.Length);
}
}

argsは文字列の配列です。

たとえば、次のように実行します。

Bash
dotnet run -- apple banana orange

この場合、argsには次の値が入ります。

C#
args[0] = "apple"
args[1] = "banana"
args[2] = "orange"

args.Length3になります。

最近のC#コンソールアプリでは、トップレベルステートメントという短い書き方も使われます。

C#
Console.WriteLine("引数の数: " + args.Length);

この場合でも、argsを使ってコマンドライン引数を受け取れます。

3-2. コマンドライン引数を指定して実行する方法

dotnet runで引数を渡す場合は、--の後ろに引数を書きます。

Bash
dotnet run -- Taro

C#側では次のように受け取れます。

C#
if (args.Length > 0)
{
Console.WriteLine("こんにちは、" + args[0] + "さん");
}
else
{
Console.WriteLine("名前を指定してください");
}

実行結果は次のようになります。

Bash
こんにちは、Taroさん

--は、dotnet run自体のオプションと、実行するアプリケーションに渡す引数を区別するために使います。

3-3. 複数の引数を受け取るサンプル

複数の引数を受け取る例を見てみましょう。

C#
if (args.Length < 2)
{
Console.WriteLine("使い方: dotnet run -- <名前> <年齢>");
return;
}

string name = args[0];
string ageText = args[1];

Console.WriteLine($"名前: {name}");
Console.WriteLine($"年齢: {ageText}");

実行コマンドは次のとおりです。

Bash
dotnet run -- Yamada 30

実行結果は次のようになります。

Bash
名前: Yamada
年齢: 30

年齢を数値として扱いたい場合は、int.TryParse()を使うと安全です。

C#
if (args.Length < 2)
{
Console.WriteLine("使い方: dotnet run -- <名前> <年齢>");
return;
}

string name = args[0];

if (!int.TryParse(args[1], out int age))
{
Console.WriteLine("年齢は数値で指定してください");
return;
}

Console.WriteLine($"{name}さんは{age}歳です");

このように、コマンドライン引数は必ず文字列として渡されるため、数値として使う場合は変換処理が必要です。

3-4. 引数がない場合のエラー対策

初心者がよくやるミスは、引数が存在しないのにargs[0]を参照してしまうことです。

C#
Console.WriteLine(args[0]);

このコードを引数なしで実行すると、配列の範囲外アクセスでエラーになります。

そのため、必ずargs.Lengthを確認しましょう。

C#
if (args.Length == 0)
{
Console.WriteLine("引数が指定されていません");
return;
}

Console.WriteLine(args[0]);

複数の引数が必要な場合は、必要な数だけチェックします。

C#
if (args.Length < 2)
{
Console.WriteLine("引数が不足しています");
Console.WriteLine("使い方: dotnet run -- <入力ファイル> <出力ファイル>");
return;
}

このように、最初に引数チェックを書くことで、実行時エラーを防ぎやすくなります。

3-5. 実務でよく使う引数処理の考え方

実務では、単にargs[0]args[1]で値を受け取るだけでなく、オプション形式で処理することが多いです。

たとえば、次のような実行方法です。

Bash
dotnet run -- --input data.txt --output result.txt

簡単な解析例は次のとおりです。

C#
string? input = null;
string? output = null;

for (int i = 0; i < args.Length; i++)
{
if (args[i] == "--input" && i + 1 < args.Length)
{
input = args[i + 1];
i++;
}
else if (args[i] == "--output" && i + 1 < args.Length)
{
output = args[i + 1];
i++;
}
}

if (input == null || output == null)
{
Console.WriteLine("使い方: dotnet run -- --input <入力ファイル> --output <出力ファイル>");
return;
}

Console.WriteLine($"入力: {input}");
Console.WriteLine($"出力: {output}");

小さなツールであれば、このような手書きの引数処理でも十分です。

本格的なCLIツールを作る場合は、コマンドライン引数を解析するライブラリの利用も検討するとよいでしょう。

4. C#から外部コマンドを呼び出す方法

C#では、自分のプログラムの中から外部コマンドや外部プログラムを実行できます。

たとえば、次のようなことができます。

Windowsのdirコマンドを実行する、pingで通信確認をする、バッチファイルを実行する、外部のexeファイルを起動する、PowerShellコマンドを実行する、実行結果を文字列として取得する。

これらを行うときに使う代表的なクラスがProcessです。

4-1. Processクラスとは

Processクラスは、外部プロセスを起動したり、実行結果を取得したりするためのクラスです。

使うときは、次の名前空間を指定します。

C#
using System.Diagnostics;

単純に外部プログラムを起動するだけなら、次のように書けます。

C#
using System.Diagnostics;

Process.Start("notepad.exe");

ただし、実務ではProcessStartInfoを使って、実行ファイル名、引数、作業ディレクトリ、標準出力の取得方法などを細かく指定することが多いです。

4-2. Process.Startで外部コマンドを実行する基本

外部コマンドを実行する基本形は次のとおりです。

C#
using System.Diagnostics;

var startInfo = new ProcessStartInfo
{
FileName = "notepad.exe",
UseShellExecute = true
};

Process.Start(startInfo);

この例では、メモ帳を起動します。

FileNameには実行したいプログラム名を指定します。

指定例意味
notepad.exeメモ帳を起動
cmd.exeコマンドプロンプトを起動
powershell.exeWindows PowerShellを起動
pingpingコマンドを起動
/usr/bin/lsLinux/macOSでlsを実行

外部コマンドの出力をC#側で取得したい場合は、UseShellExecutefalseにし、標準出力をリダイレクトします。RedirectStandardOutputを使う場合はUseShellExecutefalseにする必要があると公式ドキュメントでも説明されています。

4-3. コマンドプロンプトのコマンドを実行する方法

Windowsのdircopyなどは、単体のexeではなくコマンドプロンプトの内部コマンドです。

そのため、C#から実行する場合はcmd.exe /cを使います。

C#
using System.Diagnostics;

var startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = "/c dir",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};

using var process = Process.Start(startInfo);

if (process == null)
{
Console.WriteLine("プロセスを開始できませんでした");
return;
}

string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();

process.WaitForExit();

Console.WriteLine(output);

if (!string.IsNullOrEmpty(error))
{
Console.WriteLine("エラー:");
Console.WriteLine(error);
}

/cは、指定したコマンドを実行したあとにcmd.exeを終了する指定です。

つまり、次の部分でdirコマンドを実行しています。

C#
Arguments = "/c dir"

4-4. PowerShellコマンドを実行する方法

PowerShellコマンドを実行する場合は、powershell.exeまたはpwshを使います。

Windows PowerShellを使う例です。

C#
using System.Diagnostics;

var startInfo = new ProcessStartInfo
{
FileName = "powershell.exe",
Arguments = "-NoProfile -Command \"Get-ChildItem\"",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};

using var process = Process.Start(startInfo);

if (process == null)
{
Console.WriteLine("PowerShellを開始できませんでした");
return;
}

string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();

process.WaitForExit();

Console.WriteLine(output);

if (!string.IsNullOrWhiteSpace(error))
{
Console.WriteLine(error);
}

PowerShell 7以降のpwshを使う場合は、次のように変更します。

C#
FileName = "pwsh"

環境によってpowershell.exepwshのどちらが使えるか異なるため、実行環境に合わせて選びましょう。

4-5. 外部プログラムやexeファイルを実行する方法

外部のexeファイルを実行する場合は、FileNameに実行ファイルのパスを指定します。

C#
using System.Diagnostics;

var startInfo = new ProcessStartInfo
{
FileName = @"C:\Tools\MyTool.exe",
Arguments = "--mode test",
UseShellExecute = false
};

Process.Start(startInfo);

パスに空白が含まれる場合でも、FileNameに実行ファイル、Argumentsに引数を分けて指定すれば扱いやすくなります。

C#
var startInfo = new ProcessStartInfo
{
FileName = @"C:\Program Files\MyApp\MyApp.exe",
Arguments = "--version",
UseShellExecute = false
};

さらに安全に引数を扱いたい場合は、ArgumentListを使う方法もあります。

C#
var startInfo = new ProcessStartInfo
{
FileName = @"C:\Program Files\MyApp\MyApp.exe",
UseShellExecute = false
};

startInfo.ArgumentList.Add("--input");
startInfo.ArgumentList.Add(@"C:\Data\sample file.txt");

Process.Start(startInfo);

ArgumentListを使うと、引数を文字列連結で組み立てる必要が少なくなり、空白や引用符の扱いでミスしにくくなります。

4-6. 実行結果をC#側で取得する方法

外部コマンドの実行結果を取得するには、RedirectStandardOutputtrueにします。

C#
using System.Diagnostics;

var startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = "/c echo Hello from command",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
};

using var process = Process.Start(startInfo);

if (process == null)
{
Console.WriteLine("プロセスを開始できませんでした");
return;
}

string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();

Console.WriteLine("取得した結果:");
Console.WriteLine(output);

実行結果は次のようになります。

Bash
取得した結果:
Hello from command

この方法を使えば、外部コマンドの結果をC#の文字列として処理できます。

4-7. 標準エラー出力を取得する方法

コマンド実行時には、通常の出力とは別にエラー出力が返されることがあります。

標準エラー出力を取得するには、RedirectStandardErrortrueにします。

C#
using System.Diagnostics;

var startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = "/c unknowncommand",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};

using var process = Process.Start(startInfo);

if (process == null)
{
Console.WriteLine("プロセスを開始できませんでした");
return;
}

string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();

process.WaitForExit();

Console.WriteLine("終了コード: " + process.ExitCode);
Console.WriteLine("標準出力:");
Console.WriteLine(output);
Console.WriteLine("標準エラー:");
Console.WriteLine(error);

ExitCode0であれば成功、0以外であればエラーを示すことが一般的です。

ただし、終了コードの意味は実行するコマンドやプログラムによって異なります。

5. C#で外部コマンドを実行するときの実用サンプル

ここからは、C#で外部コマンドを実行する実用的なサンプルを紹介します。

Windows環境を中心に説明しますが、LinuxやmacOSでの違いにも触れます。

5-1. dirコマンドを実行するサンプル

Windowsで現在のフォルダ内のファイル一覧を表示するには、dirコマンドを使います。

C#から実行する例です。

C#
using System.Diagnostics;

var startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = "/c dir",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};

using var process = Process.Start(startInfo);

if (process == null)
{
Console.WriteLine("プロセスを開始できませんでした");
return;
}

string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();

process.WaitForExit();

Console.WriteLine(output);

if (!string.IsNullOrWhiteSpace(error))
{
Console.WriteLine("エラー:");
Console.WriteLine(error);
}

特定のフォルダを対象にしたい場合は、WorkingDirectoryを指定します。

C#
var startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = "/c dir",
WorkingDirectory = @"C:\Temp",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
};

WorkingDirectoryを指定すると、そのフォルダでコマンドを実行したのと同じ扱いになります。

5-2. pingコマンドを実行するサンプル

ネットワーク疎通を確認するpingコマンドをC#から実行する例です。

C#
using System.Diagnostics;

var startInfo = new ProcessStartInfo
{
FileName = "ping",
Arguments = "google.com",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};

using var process = Process.Start(startInfo);

if (process == null)
{
Console.WriteLine("pingを開始できませんでした");
return;
}

string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();

process.WaitForExit();

Console.WriteLine(output);

if (process.ExitCode != 0)
{
Console.WriteLine("pingに失敗しました");
Console.WriteLine(error);
}

Windowsでは回数指定に-nを使います。

Bash
ping -n 4 google.com

LinuxやmacOSでは、回数指定に-cを使うことが一般的です。

Bash
ping -c 4 google.com

そのため、クロスプラットフォーム対応する場合はOSごとに引数を切り替える必要があります。

C#
string arguments;

if (OperatingSystem.IsWindows())
{
arguments = "-n 4 google.com";
}
else
{
arguments = "-c 4 google.com";
}

5-3. ファイルやフォルダを開くサンプル

C#からファイルやフォルダを開きたい場合は、UseShellExecute = trueを使うと便利です。

たとえば、フォルダをエクスプローラーで開く例です。

C#
using System.Diagnostics;

var startInfo = new ProcessStartInfo
{
FileName = @"C:\Temp",
UseShellExecute = true
};

Process.Start(startInfo);

テキストファイルを既定のアプリで開く場合は、次のように書けます。

C#
var startInfo = new ProcessStartInfo
{
FileName = @"C:\Temp\sample.txt",
UseShellExecute = true
};

Process.Start(startInfo);

UseShellExecuteは、OSのシェルを使ってプロセスを開始するかどうかを指定するプロパティです。公式ドキュメントでも、OSシェルを使用してプロセスを開始するかどうかを示す値と説明されています。

ただし、標準出力を取得したい場合はUseShellExecute = falseにする必要があります。

5-4. batファイルを実行するサンプル

WindowsのバッチファイルをC#から実行する例です。

C#
using System.Diagnostics;

var startInfo = new ProcessStartInfo
{
FileName = @"C:\Scripts\sample.bat",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};

using var process = Process.Start(startInfo);

if (process == null)
{
Console.WriteLine("batファイルを開始できませんでした");
return;
}

string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();

process.WaitForExit();

Console.WriteLine(output);

if (!string.IsNullOrWhiteSpace(error))
{
Console.WriteLine(error);
}

バッチファイルをcmd.exe経由で実行することもできます。

C#
var startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = @"/c ""C:\Scripts\sample.bat""",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};

パスに空白が含まれる可能性がある場合は、引用符の扱いに注意しましょう。

5-5. 管理者権限が必要なコマンドを扱う場合の注意点

一部のコマンドは、管理者権限がないと実行できません。

たとえば、システム設定の変更、サービスの開始・停止、Program Files配下への書き込みなどは、権限不足で失敗することがあります。

管理者権限で実行したい場合、WindowsではVerb = "runas"を使う方法があります。

C#
using System.Diagnostics;

var startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = "/c net start",
UseShellExecute = true,
Verb = "runas"
};

Process.Start(startInfo);

ただし、この方法ではユーザーアカウント制御の確認画面が表示されます。

また、UseShellExecute = trueの場合、標準出力のリダイレクトはできません。

そのため、管理者権限が必要な処理では、画面操作、ログ出力、権限設計を事前に考える必要があります。

5-6. WindowsとLinux・macOSでコマンドが異なる場合の対応

C#はWindowsだけでなく、LinuxやmacOSでも動作します。

しかし、OSによって使えるコマンドは異なります。

処理WindowsLinux/macOS
ファイル一覧dirls
ファイルコピーcopycp
ファイル削除delrm
ping回数指定-n-c
シェルcmd.exe/bin/bash/bin/sh

OSごとにコマンドを切り替える例です。

C#
using System.Diagnostics;

string fileName;
string arguments;

if (OperatingSystem.IsWindows())
{
fileName = "cmd.exe";
arguments = "/c dir";
}
else
{
fileName = "/bin/bash";
arguments = "-c \"ls\"";
}

var startInfo = new ProcessStartInfo
{
FileName = fileName,
Arguments = arguments,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true
};

using var process = Process.Start(startInfo);

if (process == null)
{
Console.WriteLine("プロセスを開始できませんでした");
return;
}

string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();

Console.WriteLine(output);

クロスプラットフォーム対応が必要な場合は、なるべくOSコマンドに依存しない方法を選ぶのが理想です。

たとえば、ファイル一覧を取得するだけなら、dirlsではなくC#のDirectory.GetFiles()を使う方が安全です。

C#
foreach (string file in Directory.GetFiles("."))
{
Console.WriteLine(file);
}

6. C#のコマンド実行でよくあるエラーと解決方法

C#でコマンドを扱うと、環境設定、パス、権限、文字コードなどが原因でエラーになることがあります。

ここでは、初心者がよく遭遇するエラーと解決方法を紹介します。

6-1. dotnetが認識されない場合

次のようなエラーが表示されることがあります。

Bash
'dotnet' is not recognized as an internal or external command

日本語環境では、次のようなメッセージになることもあります。

Bash
'dotnet' は、内部コマンドまたは外部コマンドとして認識されていません

主な原因は次のとおりです。

.NET SDKがインストールされていない、環境変数PATHにdotnetのパスが通っていない、インストール後にターミナルを再起動していない。

まず、.NET SDKをインストールしているか確認します。

次に、新しいターミナルを開き直して、次のコマンドを実行します。

Bash
dotnet --version

それでも認識されない場合は、環境変数PATHを確認しましょう。

Windowsでは通常、次のような場所にdotnet.exeがあります。

C:\Program Files\dotnet\

このパスが環境変数PATHに含まれているか確認してください。

6-2. cscが認識されない場合

C#のコンパイラとしてcscというコマンドを見かけることがあります。

しかし、現在の.NET開発では、初心者が直接cscを使う場面は多くありません。

次のようなエラーが出ることがあります。

Bash
'csc' is not recognized as an internal or external command

この場合、無理にcscを使うより、dotnetコマンドを使うのがおすすめです。

Bash
dotnet new console -n SampleApp
cd SampleApp
dotnet run

学習の初期段階では、cscよりもdotnet newdotnet builddotnet runを使う方がわかりやすく、実務にもつながりやすいです。

6-3. プロジェクトが見つからない場合

dotnet runを実行したときに、プロジェクトが見つからないというエラーが出ることがあります。

原因は、現在のフォルダに.csprojファイルがないことです。

たとえば、次のような構成だとします。

CSharpCommandSample/
CSharpCommandSample.csproj
Program.cs

この場合、dotnet runCSharpCommandSampleフォルダの中で実行する必要があります。

Bash
cd CSharpCommandSample
dotnet run

現在のフォルダを確認するには、Windowsでは次のコマンドを使います。

Bash
cd

LinuxやmacOSでは次のコマンドです。

Bash
pwd

フォルダの中身を確認するには、Windowsではdir、LinuxやmacOSではlsを使います。

6-4. 外部コマンドが実行されない場合

C#から外部コマンドを実行しようとしても、何も起きないことがあります。

主な原因は次のとおりです。

FileNameが間違っている、実行ファイルのパスが間違っている、PATHが通っていない、UseShellExecuteの指定が適切でない、引数の書き方が間違っている、作業ディレクトリが違う。

まずは、実行したいコマンドをターミナルで直接実行できるか確認しましょう。

Bash
ping google.com

ターミナルでも実行できない場合、C#からも実行できません。

次に、C#側でExitCode、標準出力、標準エラーを確認しましょう。

C#
Console.WriteLine("終了コード: " + process.ExitCode);
Console.WriteLine("標準出力: " + output);
Console.WriteLine("標準エラー: " + error);

エラー内容を表示すれば、原因を特定しやすくなります。

6-5. パスに空白が含まれる場合

Windowsでは、次のようにパスに空白が含まれることがあります。

C:\Program Files\My App\tool.exe

このようなパスを文字列連結でコマンドに埋め込むと、空白で分割されて失敗することがあります。

悪い例です。

C#
Arguments = "/c C:\\Program Files\\My App\\tool.exe";

この場合、C:\Programまでが別の引数として扱われる可能性があります。

基本的には、実行ファイルと引数を分けて指定しましょう。

C#
var startInfo = new ProcessStartInfo
{
FileName = @"C:\Program Files\My App\tool.exe",
UseShellExecute = false
};

引数に空白を含む値を渡す場合は、ArgumentListを使うと安全です。

C#
startInfo.ArgumentList.Add("--file");
startInfo.ArgumentList.Add(@"C:\Data\sample file.txt");

6-6. 標準出力が文字化けする場合

外部コマンドの出力を取得したときに、日本語が文字化けすることがあります。

原因は、コマンド側の文字コードとC#側の読み取り文字コードが一致していないためです。

ProcessStartInfoでは、標準出力のエンコーディングを指定できます。

C#
using System.Diagnostics;
using System.Text;

var startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = "/c dir",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
StandardOutputEncoding = Encoding.UTF8,
StandardErrorEncoding = Encoding.UTF8,
CreateNoWindow = true
};

ただし、Windowsのコマンドプロンプトでは環境によって文字コードが異なる場合があります。

必要に応じて、chcp 65001でUTF-8に変更してから実行する方法もあります。

C#
Arguments = "/c chcp 65001 > nul && dir";

文字化け対策は環境依存になりやすいため、まずはターミナル側の文字コードと、C#側の読み取り設定を確認しましょう。

6-7. コマンド実行後に画面がすぐ閉じる場合

C#で作成したexeをダブルクリックして実行すると、処理が終わった瞬間に画面が閉じることがあります。

これはエラーではなく、コンソールアプリが終了したためです。

対策として、開発中はターミナルから実行しましょう。

Bash
dotnet run

または、最後に入力待ちを入れます。

C#
Console.WriteLine("Enterキーで終了します");
Console.ReadLine();

ただし、実務用のツールでは、不要な入力待ちを入れると自動実行の邪魔になることがあります。

開発中の確認用として使うのがおすすめです。

6-8. 権限不足で実行できない場合

次のようなエラーが出る場合があります。

Access is denied.

または日本語で次のように表示されることもあります。

アクセスが拒否されました。

主な原因は、ファイルやフォルダへのアクセス権がない、管理者権限が必要、実行ファイルがブロックされている、ウイルス対策ソフトに制限されている、などです。

まずは、対象のコマンドを手動で実行できるか確認します。

管理者権限が必要な場合は、アプリ全体を管理者として実行するか、Verb = "runas"で昇格実行する必要があります。

ただし、管理者権限を前提にした設計は、利用者に負担をかけます。

可能であれば、管理者権限が不要な場所にファイルを保存する、ユーザーフォルダを使う、必要最小限の処理だけを昇格する、といった設計にしましょう。

7. C#でコマンドを安全に実行するための注意点

C#から外部コマンドを実行できると便利ですが、使い方を間違えると危険です。

特に、ユーザー入力をそのままコマンドに渡す処理は注意が必要です。

7-1. ユーザー入力をそのままコマンドに渡さない

次のようなコードは危険です。

C#
Console.Write("ファイル名を入力してください: ");
string? fileName = Console.ReadLine();

var startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = "/c type " + fileName,
UseShellExecute = false
};

ユーザーが通常のファイル名を入力するだけなら動作します。

しかし、悪意のある入力をされた場合、想定外のコマンドが実行される可能性があります。

たとえば、コマンドを連結する記号が入力されると、別の処理が実行される危険があります。

ユーザー入力を扱う場合は、許可する文字を制限する、ファイルの存在を確認する、コマンド文字列として連結しない、といった対策が必要です。

7-2. コマンドインジェクションのリスク

コマンドインジェクションとは、外部から入力された文字列によって、意図しないコマンドが実行されてしまう脆弱性です。

たとえば、次のように文字列連結でコマンドを組み立てる処理は危険です。

C#
Arguments = "/c ping " + userInput;

通常は次のような入力を想定しているかもしれません。

google.com

しかし、入力内容によっては別のコマンドをつなげられる可能性があります。

安全にするには、次のような対策が必要です。

入力値を検証する、許可リスト方式にする、シェルを経由しない、実行ファイルと引数を分ける、ArgumentListを使う、不要な外部コマンド実行を避ける。

特にWebアプリや社内ツールで外部コマンドを実行する場合は、セキュリティ上のリスクを十分に検討してください。

7-3. 実行するコマンドと引数を分けて扱う

安全性と保守性を高めるには、コマンド全体をひとつの文字列として組み立てるのではなく、実行ファイルと引数を分けて扱います。

避けたい例です。

C#
Arguments = "/c ping " + host;

改善例です。

C#
var startInfo = new ProcessStartInfo
{
FileName = "ping",
UseShellExecute = false,
RedirectStandardOutput = true
};

startInfo.ArgumentList.Add(host);

さらに、hostの値も検証しましょう。

C#
string host = "example.com";

if (host.Contains('&') || host.Contains('|') || host.Contains(';'))
{
Console.WriteLine("不正な入力です");
return;
}

本格的には、許可する形式を正規表現で制限するなどの方法を使います。

7-4. WorkingDirectoryを正しく指定する

外部コマンドは、どのフォルダで実行するかによって結果が変わることがあります。

たとえば、相対パスを使うコマンドでは、作業ディレクトリが重要です。

C#
var startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = "/c dir",
WorkingDirectory = @"C:\Temp",
UseShellExecute = false,
RedirectStandardOutput = true
};

WorkingDirectoryを明示しておくと、どの場所でコマンドが実行されるのかがわかりやすくなります。

特に、サービス、タスクスケジューラ、Webアプリなどから実行する場合、カレントディレクトリが想定と違うことがあります。

相対パスに頼らず、必要に応じて絶対パスを使いましょう。

7-5. タイムアウト処理を入れる

外部コマンドは、いつまでも終了しない可能性があります。

たとえば、ネットワーク待ち、入力待ち、処理のハングなどです。

そのため、実務ではタイムアウト処理を入れることが重要です。

C#
using System.Diagnostics;

var startInfo = new ProcessStartInfo
{
FileName = "ping",
Arguments = "google.com",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true
};

using var process = Process.Start(startInfo);

if (process == null)
{
Console.WriteLine("プロセスを開始できませんでした");
return;
}

bool exited = process.WaitForExit(5000);

if (!exited)
{
process.Kill();
Console.WriteLine("タイムアウトしたためプロセスを終了しました");
return;
}

string output = process.StandardOutput.ReadToEnd();
Console.WriteLine(output);

この例では、5秒以内に終了しない場合、プロセスを強制終了します。

ただし、Kill()は強制終了なので、ファイル書き込み中のプロセスなどに使う場合は注意が必要です。

7-6. 例外処理とログ出力を行う

外部コマンドの実行では、さまざまな例外が発生する可能性があります。

実行ファイルが見つからない、アクセス権がない、引数が不正、作業ディレクトリが存在しない、プロセス開始に失敗する、などです。

そのため、try-catchで例外処理を書いておくと安全です。

C#
using System.Diagnostics;

try
{
var startInfo = new ProcessStartInfo
{
FileName = "ping",
Arguments = "google.com",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true
};

using var process = Process.Start(startInfo);

if (process == null)
{
Console.WriteLine("プロセスを開始できませんでした");
return;
}

string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();

process.WaitForExit();

Console.WriteLine(output);

if (process.ExitCode != 0)
{
Console.WriteLine("エラーが発生しました");
Console.WriteLine(error);
}
}
catch (Exception ex)
{
Console.WriteLine("例外が発生しました");
Console.WriteLine(ex.Message);
}

実務では、画面に表示するだけでなく、ログファイルやログ基盤に記録することも重要です。

特に外部コマンドの失敗原因は、実行環境に依存することが多いため、FileNameArgumentsWorkingDirectoryExitCode、標準エラー出力をログに残しておくと調査しやすくなります。

8. C#のコマンド実行で知っておきたい関連知識

ここでは、C#でコマンドを扱うときに知っておくと理解が深まる関連知識を紹介します。

8-1. コマンドプロンプトとPowerShellの違い

Windowsには、コマンドプロンプトとPowerShellがあります。

どちらもコマンドを実行できますが、性質が異なります。

種類特徴
コマンドプロンプト従来のWindowsコマンドを実行する環境
PowerShellオブジェクト指向のシェル。管理作業や自動化に強い
Windows TerminalコマンドプロンプトやPowerShellなどを開くためのターミナルアプリ

C#からコマンドプロンプトの内部コマンドを実行する場合は、次のようにします。

C#
FileName = "cmd.exe";
Arguments = "/c dir";

PowerShellコマンドを実行する場合は、次のようにします。

C#
FileName = "powershell.exe";
Arguments = "-NoProfile -Command \"Get-ChildItem\"";

同じ「ファイル一覧を表示する」処理でも、使うシェルによって書き方が変わります。

8-2. dotnet runとexe実行の違い

dotnet runと生成されたexeを直接実行する方法には違いがあります。

開発中によく使うのは次のコマンドです。

Bash
dotnet run

これは、プロジェクトをビルドして実行するためのコマンドです。

一方、ビルド後に生成されたexeを直接実行することもできます。

Bash
bin\Debug\net8.0\SampleApp.exe

違いを整理すると次のようになります。

実行方法主な用途
dotnet run開発中の実行
dotnet build後のexe実行ビルド結果の確認
dotnet publish後のexe実行配布用アプリの実行

初心者のうちは、開発中はdotnet runを使えば問題ありません。

配布や本番環境での実行を考える段階になったら、dotnet publishも学ぶとよいでしょう。

8-3. DebugビルドとReleaseビルドの違い

C#のビルドには、主にDebugとReleaseがあります。

種類特徴
Debug開発・デバッグ向け
Release配布・本番実行向け

通常のdotnet buildでは、Debugビルドが使われます。

Releaseビルドを行うには、次のように指定します。

Bash
dotnet build -c Release

実行する場合は次のように指定できます。

Bash
dotnet run -c Release

Releaseビルドは最適化されるため、本番利用や性能確認ではRelease構成を使うのが一般的です。

8-4. 同期実行と非同期実行の違い

外部コマンドを実行するとき、処理の完了を待つかどうかで同期実行と非同期実行に分けられます。

同期実行は、外部コマンドが終わるまでC#側の処理を待つ方法です。

C#
process.WaitForExit();

非同期実行は、待機中に他の処理を止めにくい方法です。

C#
await process.WaitForExitAsync();

標準出力と標準エラーを安全に取得したい場合は、非同期で読み取る方法が便利です。

C#
using System.Diagnostics;

var startInfo = new ProcessStartInfo
{
FileName = "ping",
Arguments = "google.com",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};

using var process = new Process();
process.StartInfo = startInfo;

process.Start();

Task<string> outputTask = process.StandardOutput.ReadToEndAsync();
Task<string> errorTask = process.StandardError.ReadToEndAsync();

await process.WaitForExitAsync();

string output = await outputTask;
string error = await errorTask;

Console.WriteLine(output);

if (!string.IsNullOrWhiteSpace(error))
{
Console.WriteLine(error);
}

出力が多いコマンドを扱う場合、標準出力と標準エラーの読み取り方法に注意しないと、処理が止まることがあります。

実務では、非同期読み取りも選択肢に入れるとよいでしょう。

8-5. ProcessStartInfoの主要プロパティ

ProcessStartInfoでよく使うプロパティを整理します。

プロパティ説明
FileName実行するファイル名またはコマンド
Argumentsコマンドに渡す引数
ArgumentList引数をリスト形式で追加
UseShellExecuteOSのシェルを使うかどうか
RedirectStandardOutput標準出力を取得するかどうか
RedirectStandardError標準エラー出力を取得するかどうか
CreateNoWindow新しいウィンドウを表示しないかどうか
WorkingDirectory作業ディレクトリ
StandardOutputEncoding標準出力の文字コード
StandardErrorEncoding標準エラー出力の文字コード
Verbrunasなどの動作指定

特によく使う組み合わせは次の形です。

C#
var startInfo = new ProcessStartInfo
{
FileName = "実行するコマンド",
Arguments = "引数",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};

外部コマンドの結果をC#側で取得したい場合は、この形を基本として覚えるとよいでしょう。

9. C#コマンドに関するよくある質問

最後に、C#のコマンドに関するよくある質問をまとめます。

9-1. C#はコマンドプロンプトだけで実行できる?

はい、実行できます。

.NET SDKがインストールされていれば、コマンドプロンプトやPowerShellからC#プロジェクトを作成・ビルド・実行できます。

基本的な流れは次のとおりです。

Bash
dotnet new console -n SampleApp
cd SampleApp
dotnet run

Visual Studioを使わなくても、C#のコンソールアプリはコマンドだけで実行できます。

9-2. Visual StudioなしでC#を実行できる?

はい、できます。

Visual Studioがなくても、.NET SDKとテキストエディタがあればC#を実行できます。

たとえば、Visual Studio Code、メモ帳、VimなどでProgram.csを編集し、ターミナルで次のように実行できます。

Bash
dotnet run

ただし、Visual Studioにはデバッグ、補完、GUI操作などの便利な機能があります。

初心者の場合、学習スタイルに合わせて、Visual Studio、Visual Studio Code、コマンドラインを使い分けるとよいでしょう。

9-3. C#からcmdコマンドを実行するには?

C#からcmdコマンドを実行するには、ProcessStartInfocmd.exeを指定し、引数に/cと実行したいコマンドを指定します。

C#
using System.Diagnostics;

var startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = "/c dir",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
};

using var process = Process.Start(startInfo);

if (process == null)
{
return;
}

string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();

Console.WriteLine(output);

dircopydelなどのcmd内部コマンドは、このようにcmd.exe /c経由で実行します。

9-4. C#からPowerShellを実行するには?

C#からPowerShellを実行するには、powershell.exeまたはpwshを指定します。

C#
using System.Diagnostics;

var startInfo = new ProcessStartInfo
{
FileName = "powershell.exe",
Arguments = "-NoProfile -Command \"Get-Date\"",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
};

using var process = Process.Start(startInfo);

if (process == null)
{
return;
}

string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();

Console.WriteLine(output);

PowerShell 7以降を使う場合は、環境に応じてFileName = "pwsh"を指定します。

9-5. C#でコマンドの実行結果を文字列で取得するには?

標準出力をリダイレクトして、StandardOutput.ReadToEnd()で取得します。

C#
using System.Diagnostics;

var startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = "/c echo Hello",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};

using var process = Process.Start(startInfo);

if (process == null)
{
Console.WriteLine("プロセスを開始できませんでした");
return;
}

string result = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();

process.WaitForExit();

Console.WriteLine("結果:");
Console.WriteLine(result);

if (!string.IsNullOrWhiteSpace(error))
{
Console.WriteLine("エラー:");
Console.WriteLine(error);
}

ポイントは、UseShellExecute = falseRedirectStandardOutput = trueを指定することです。

9-6. C#で外部コマンドを非表示で実行するには?

外部コマンドを非表示で実行したい場合は、CreateNoWindow = trueを指定します。

C#
var startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = "/c dir",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};

また、ウィンドウを表示したくない場合は、標準出力をC#側で受け取る設計にするとよいです。

C#
string output = process.StandardOutput.ReadToEnd();

ただし、UseShellExecute = trueで外部アプリを起動する場合、アプリ側のウィンドウが表示されることがあります。

非表示実行が必要な場合は、実行するプログラムの種類や起動方法に応じて設定を確認しましょう。

まとめ

C#の「コマンド」には、C#プログラムを実行するためのコマンド、C#から外部コマンドを呼び出す処理、コマンドライン引数など、複数の意味があります。

初心者がまず覚えるべき基本は、次の3つです。

Bash
dotnet new console
dotnet build
dotnet run

C#プログラムをコマンドで実行する場合は、.NET SDKをインストールし、dotnet runで実行します。

コマンドライン引数を受け取る場合は、argsを使います。

C#
Console.WriteLine(args[0]);

ただし、引数がない場合に備えて、必ずargs.Lengthを確認しましょう。

C#から外部コマンドを実行する場合は、ProcessクラスとProcessStartInfoを使います。

C#
var startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = "/c dir",
UseShellExecute = false,
RedirectStandardOutput = true
};

外部コマンドの実行結果を取得するには、RedirectStandardOutputを使います。

エラー内容を確認するには、RedirectStandardErrorも指定します。

また、C#からコマンドを実行するときは、セキュリティにも注意が必要です。

ユーザー入力をそのままコマンドに渡さない、実行ファイルと引数を分ける、WorkingDirectoryを明示する、タイムアウトを設定する、例外処理とログ出力を行う、といった対策を意識しましょう。

C#のコマンド実行は、ファイル処理、自動化ツール、社内システム、運用スクリプト連携など、さまざまな場面で役立ちます。

まずはdotnet runでC#プログラムを実行するところから始め、次にコマンドライン引数、最後にProcessを使った外部コマンド実行へ進むと、無理なく理解できます。