C# Scripting入門:Roslynで.csxを実行する方法から活用例・注意点まで徹底解説

はじめに

C# Scriptingは、C#コードをスクリプトのように手軽に実行できる仕組みです。Roslynを使えば、.csxファイルの実行や、アプリケーション内での動的なC#コード実行を実現できます。

本記事では、C# Scriptingの基本、.csxの実行方法、Roslyn APIの使い方、活用例、注意点、セキュリティ設計までを解説します。

1. C# Scriptingとは何か

1-1. C# Scriptingの概要と通常のC#プログラムとの違い

C# Scriptingは、C#の文法を使ってコードを逐次実行できる仕組みです。通常のC#プログラムはプロジェクトを作成し、ビルドして実行します。一方、C# Scriptingでは短いコードをそのまま評価したり、.csxファイルとして実行したりできます。

1-2. .csxファイルとは何か

.csxはC# Scriptファイルの拡張子です。通常の.csファイルとは異なり、トップレベルに文を書けます。

C#
Console.WriteLine("Hello, C# Scripting!");

このように、クラスやMainメソッドを書かずに実行できます。

1-3. RoslynとC# Scriptingの関係

Roslynは、Microsoftが提供するC#およびVB.NETのコンパイラプラットフォームです。C# ScriptingはRoslynの機能を利用して、C#コードの解析、コンパイル、実行を行います。

1-4. C# Scriptingが注目される理由

C# Scriptingは、検証コード、自動化、動的なルール実行、プロトタイピングに向いています。C#や.NETの資産をそのまま使えるため、.NET開発者にとって導入しやすい点が魅力です。

2. C# Scriptingでできること・主な活用シーン

2-1. 小さな処理や検証コードをすばやく実行する

APIの動作確認、文字列処理、計算ロジックの検証などを、プロジェクト作成なしで試せます。

2-2. 業務ツールや自動化スクリプトに活用する

ファイル整理、ログ集計、CSV変換、定型処理の自動化などに利用できます。

2-3. アプリケーションに動的な処理を組み込む

ユーザーが定義した式やルールを、アプリケーション側で実行する用途に使えます。

2-4. 設定・ルール・計算式を外部スクリプト化する

割引計算、判定条件、帳票出力ルールなどを外部ファイル化すれば、アプリ本体を変更せずにロジックを差し替えられます。

2-5. 学習・プロトタイピング用途で使う

C#の文法確認やLINQの試行、ライブラリの動作確認にも便利です。

3. C# Scriptingを始めるための準備

3-1. 必要な開発環境

C# Scriptingを使うには、.NET SDK、Visual Studio、VS Codeなどの環境を用意します。アプリに組み込む場合は、NuGetパッケージを追加します。

3-2. Roslyn関連パッケージの導入

Roslyn APIでスクリプトを実行するには、次のパッケージを導入します。

Bash
dotnet add package Microsoft.CodeAnalysis.CSharp.Scripting

3-3. Microsoft.CodeAnalysis.CSharp.Scriptingの役割

このパッケージは、C#コードを文字列として評価したり、スクリプトとして継続実行したりするためのAPIを提供します。

3-4. csi・dotnet-script・Roslyn APIの違い

csiはC# Interactive用の実行環境です。dotnet-script.csx実行に便利なCLIツールです。Roslyn APIは、自作アプリケーションにスクリプト実行機能を組み込むために使います。

3-5. どの実行方法を選ぶべきか

手軽に試すならcsi.csxファイルを実用的に管理するならdotnet-script、アプリ内で動的処理を実行するならRoslyn APIが適しています。

4. .csxファイルを実行する基本手順

4-1. .csxファイルの基本構文

.csxでは、トップレベルに処理を書けます。

C#
var name = "Roslyn";
Console.WriteLine($"Hello, {name}");

4-2. csiで.csxを実行する方法

script.csxを作成し、次のように実行します。

Bash
csi script.csx

4-3. dotnet-scriptで.csxを実行する方法

dotnet-scriptを使う場合は、次のように実行します。

Bash
dotnet script script.csx

4-4. NuGetパッケージを.csx内で読み込む方法

.csxでは、環境によって次のようにNuGetパッケージを参照できます。

C#
#r "nuget: Newtonsoft.Json"

using Newtonsoft.Json;

4-5. using・参照・外部ファイルの扱い方

名前空間は通常のC#と同じくusingで指定します。外部DLLを使う場合は#r、別スクリプトを読み込む場合は#loadを使います。

C#
#load "common.csx"
#r "MyLibrary.dll"

4-6. 実行時によくあるエラーと対処法

よくあるエラーは、参照不足、名前空間不足、パッケージのバージョン不一致です。using#r、NuGet参照、実行環境の.NETバージョンを確認しましょう。

5. Roslyn APIでC#スクリプトを実行する方法

5-1. CSharpScript.EvaluateAsyncの基本

EvaluateAsyncは、コードを評価して結果を取得するAPIです。

C#
using Microsoft.CodeAnalysis.CSharp.Scripting;

var result = await CSharpScript.EvaluateAsync<int>("1 + 2");
Console.WriteLine(result);

5-2. CSharpScript.RunAsyncの基本

RunAsyncは、スクリプトの実行状態を取得したい場合に使います。

C#
var state = await CSharpScript.RunAsync("var x = 10;");

5-3. ScriptOptionsで参照や名前空間を設定する

外部アセンブリや名前空間を指定するにはScriptOptionsを使います。

C#
var options = ScriptOptions.Default
.AddImports("System", "System.Linq")
.AddReferences(typeof(object).Assembly);

5-4. Globalsを使って外部データを渡す

アプリ側のデータをスクリプトに渡すにはGlobalsを使います。

C#
public class Globals
{
public int Price { get; set; }
}

var globals = new Globals { Price = 1000 };
var result = await CSharpScript.EvaluateAsync<int>(
"Price * 2",
globals: globals
);

5-5. 戻り値・例外・実行結果を取得する

戻り値はEvaluateAsyncで取得できます。例外は通常のtry-catchで処理します。

C#
try
{
var result = await CSharpScript.EvaluateAsync<int>("10 / 0");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}

5-6. スクリプトを継続実行する方法

RunAsyncで取得した状態に対してContinueWithAsyncを使うと、変数を引き継いで実行できます。

C#
var state = await CSharpScript.RunAsync("var x = 10;");
state = await state.ContinueWithAsync("x += 5;");

6. C# Scriptingの実践サンプル

6-1. 文字列や数値を処理する簡単なスクリプト

C#
var text = "csharp scripting";
Console.WriteLine(text.ToUpper());

6-2. ファイル操作を行うスクリプト

C#
using System.IO;

var lines = File.ReadAllLines("input.txt");
File.WriteAllLines("output.txt", lines.Select(x => x.ToUpper()));

6-3. JSONやCSVを処理するスクリプト

C#
#r "nuget: Newtonsoft.Json"

using Newtonsoft.Json;

var json = "{\"name\":\"Taro\"}";
dynamic obj = JsonConvert.DeserializeObject(json);
Console.WriteLine(obj.name);

6-4. 外部ライブラリを使ったスクリプト

NuGetパッケージを使えば、通常のC#開発と同じように外部ライブラリを利用できます。

6-5. アプリケーション内でユーザー定義ロジックを実行する例

C#
var formula = "Price >= 1000";
var result = await CSharpScript.EvaluateAsync<bool>(
formula,
globals: new Globals { Price = 1200 }
);

このように、業務ルールを外部化できます。

7. C# Scriptingを使うメリット

7-1. コンパイルなしで素早く実行できる

短い処理をすぐに試せるため、検証や運用作業が効率化します。

7-2. C#の知識をそのまま活かせる

既存のC#開発者であれば、新しい言語を覚えずに使えます。

7-3. 既存の.NET資産を利用しやすい

.NETライブラリ、NuGetパッケージ、自社ライブラリを活用できます。

7-4. 動的な拡張機能を実装しやすい

アプリ本体を再ビルドせずに、処理内容を変更できます。

7-5. 開発・検証・運用を効率化できる

一時的な検証、データ変換、運用スクリプトに向いています。

8. C# Scriptingの注意点とデメリット

8-1. セキュリティリスクに注意する

C# Scriptingは強力ですが、ファイル操作、ネットワーク通信、プロセス実行なども可能です。

8-2. 信頼できないスクリプトを実行してはいけない理由

悪意あるスクリプトを実行すると、情報漏えい、ファイル削除、不正アクセスにつながる可能性があります。

8-3. パフォーマンス面の注意点

初回実行時にはコンパイルコストが発生します。頻繁に実行する場合はキャッシュや事前検証を検討しましょう。

8-4. デバッグや保守が難しくなるケース

スクリプトが増えすぎると、通常のC#コードより管理しにくくなる場合があります。

8-5. バージョン差異や依存関係の管理に注意する

.NETバージョン、NuGetパッケージ、実行環境の差異によって動作が変わることがあります。

8-6. 本番環境で使う際の判断基準

本番環境では、実行権限、ログ、監査、障害対応、保守性を十分に検討する必要があります。

9. セキュアにC# Scriptingを使うための設計ポイント

9-1. 実行できる処理を制限する

必要なAPIだけを公開し、自由に任意コードを実行できる設計は避けます。

9-2. 入力値を検証する

ユーザー入力をそのままスクリプトに渡すのは危険です。型、範囲、文字列長を検証しましょう。

9-3. ファイル・ネットワーク・プロセス操作を制御する

ファイル削除、外部通信、プロセス起動などは特に注意が必要です。

9-4. 実行ログと監査ログを残す

誰が、いつ、どのスクリプトを実行したかを記録します。

9-5. タイムアウトやリソース制限を設ける

無限ループや高負荷処理を防ぐため、実行時間やメモリ使用量の制限を検討します。

9-6. サンドボックス化を検討する

完全な安全性をRoslyn APIだけで保証するのは困難です。必要に応じて別プロセス、コンテナ、権限制限を組み合わせます。

10. C# Scriptingでよくある疑問

10-1. C# Scriptingは今でも使えるのか

はい、RoslynのAPIや.csx実行環境を使えば現在でも利用できます。

10-2. .csxと通常の.csファイルの違いは何か

.csxはスクリプト向けで、トップレベルに処理を書けます。.csは通常のC#ソースファイルです。

10-3. Visual StudioやVS Codeで編集できるのか

編集できます。C#拡張機能を入れると、補完や構文ハイライトを利用しやすくなります。

10-4. NuGetパッケージは使えるのか

実行環境によっては、.csx内でNuGetパッケージを参照できます。

10-5. ASP.NET Coreアプリに組み込めるのか

組み込めます。ただし、セキュリティと運用設計を慎重に行う必要があります。

10-6. PowerShellやPythonの代わりになるのか

用途によります。.NET資産を活かしたい場合はC# Scriptingが有利です。一方、OS操作や汎用スクリプトではPowerShellやPythonが適する場合もあります。

11. C# Scriptingと他の選択肢の比較

11-1. C# ScriptingとPowerShellの違い

PowerShellは管理作業やWindows操作に強く、C# ScriptingはC#コードや.NET資産の活用に強みがあります。

11-2. C# ScriptingとPythonスクリプトの違い

Pythonはデータ分析や自動化で広く使われます。C# Scriptingは.NETアプリとの統合に向いています。

11-3. C# ScriptingとSource Generatorの違い

Source Generatorはコンパイル時にコードを生成する仕組みです。C# Scriptingは実行時にコードを評価します。

11-4. C# Scriptingとプラグイン方式の違い

プラグイン方式は明確なインターフェースで拡張します。C# Scriptingはより柔軟ですが、制御が難しくなる場合があります。

11-5. 用途別の選び方

簡単な運用処理ならPowerShell、データ処理ならPython、.NETアプリ内の動的ロジックならC# Scripting、堅牢な拡張ならプラグイン方式が適しています。

12. C# Scripting導入前のチェックリスト

12-1. 実行目的が明確か

なぜC# Scriptingを使うのかを明確にしましょう。

12-2. セキュリティ要件を満たせるか

任意コード実行のリスクを許容できるか確認します。

12-3. 保守担当者が理解できるか

スクリプトを誰が管理し、レビューするのかを決めておきます。

12-4. エラー時の運用ルールがあるか

失敗時の通知、ロールバック、再実行手順を用意します。

12-5. 通常のC#実装で十分ではないか

動的実行が不要なら、通常のC#実装の方が安全で保守しやすい場合があります。

まとめ

C# Scriptingは、C#コードを手軽に実行できる便利な仕組みです。.csxファイルを使えば短い処理を素早く実行でき、Roslyn APIを使えばアプリケーション内に動的な処理を組み込めます。

一方で、C# Scriptingは任意コード実行に近い性質を持つため、セキュリティ、依存関係、パフォーマンス、保守性には注意が必要です。

小規模な検証や自動化には非常に便利ですが、本番環境で使う場合は、実行制限、ログ、タイムアウト、サンドボックス化を含めた設計が欠かせません。C#と.NETの資産を活かしながら柔軟な仕組みを作りたい場合、C# Scriptingは有力な選択肢になります。