🐕

PowerShellで簡単にC#を実行する(Windowsユーザー必見)

に公開

PowerShell は便利ですが、複雑なスクリプト構文や動作仕様が分かりづらい…。
そんなとき、C# の構文でシンプルかつ直感的にスクリプトを書きたくなります。
本記事では、PowerShell から C# を呼び出して実行する方法をまとめました。


この記事のポイント

  • PowerShell 上で C# をスクリプトとして実行する方法
  • よくあるファイル操作(サイズ比較、名前検索など)を C# で実装
  • dotnet-script を活用してコードを一時ファイルとして実行
  • 外部ライブラリ(Newtonsoft.Json など)の正しい使い方

必要な準備

以下のツールがインストールされていることを確認してください:

# .NET SDK のインストール(必要に応じて)
winget install Microsoft.DotNet.SDK.9

# dotnet-script のインストール
dotnet tool install -g dotnet-script

サンプル1:ファイルサイズの比較

$code = @"
using System;
using System.IO;

var file1 = Path.Combine(Directory.GetCurrentDirectory(), "fileA.txt");
var file2 = Path.Combine(Directory.GetCurrentDirectory(), "fileB.txt");

if (File.Exists(file1) && File.Exists(file2))
{
    var size1 = new FileInfo(file1).Length;
    var size2 = new FileInfo(file2).Length;
    Console.WriteLine($"{Path.GetFileName(file1)}: {size1} bytes");
    Console.WriteLine($"{Path.GetFileName(file2)}: {size2} bytes");
    Console.WriteLine(size1 > size2 ? "fileA is larger" : "fileB is larger");
}
else
{
    Console.WriteLine("どちらかのファイルが存在しません。");
}
"@

$tmp = [IO.Path]::Combine($env:TEMP, "size_compare_$(Get-Random).csx")
$code | Out-File $tmp -Encoding UTF8
dotnet script $tmp
Remove-Item $tmp

サンプル2:特定の名前を含むファイルの検索

$code = @"
using System;
using System.IO;

var keyword = "report";
var root = Directory.GetCurrentDirectory();
var files = Directory.GetFiles(root, "*" + keyword + "*", SearchOption.AllDirectories);

if (files.Length == 0)
{
    Console.WriteLine("見つかりませんでした");
}
else
{
    foreach (var file in files)
    {
        Console.WriteLine(file);
    }
}
"@

$tmp = [IO.Path]::Combine($env:TEMP, "search_name_$(Get-Random).csx")
$code | Out-File $tmp -Encoding UTF8
dotnet script $tmp
Remove-Item $tmp

サンプル3:JSONを使った簡単なデータ出力

$code = @"
#r "nuget: Newtonsoft.Json, 13.0.3"

using System;
using Newtonsoft.Json;

var person = new { Name = "Junya", Age = 26 };
var json = JsonConvert.SerializeObject(person, Formatting.Indented);
Console.WriteLine(json);
"@

$tmp = [IO.Path]::Combine($env:TEMP, "json_sample_$(Get-Random).csx")
$code | Out-File $tmp -Encoding UTF8
dotnet script $tmp
Remove-Item $tmp

実行結果例:

{
  "Name": "Sakaki",
  "Age": 99
}

Windows標準以外のライブラリを使いたい場合

.csx スクリプトでは、外部ライブラリを使うには以下のように明示的に記述する必要があります:

#r "nuget: Newtonsoft.Json"
using Newtonsoft.Json;

まとめ

PowerShell から C# を呼び出すことで、視認性の高いスクリプトを簡単に書くことができます。
特に、型安全性が求められる処理や外部ライブラリを活用したユースケースでは C# のメリットが際立ちます。


*English

Mastering C# Scripts with PowerShell: A Practical Guide for Windows Users

PowerShell is a powerful tool, but its scripting syntax and runtime behavior can be difficult to understand.
In such cases, writing scripts in C# with intuitive and type-safe syntax can be a more productive option.
This guide explains how to run C# scripts from PowerShell for automating common file tasks.


Key Takeaways

  • How to execute C# scripts from PowerShell
  • Implementing common file operations (e.g., size comparison, name search) using C#
  • Using dotnet-script to run C# as temporary files
  • Correctly using external libraries like Newtonsoft.Json in .csx scripts

Prerequisites

Ensure the following tools are installed on your system:

# Install .NET SDK (if needed)
winget install Microsoft.DotNet.SDK.9

# Install dotnet-script
dotnet tool install -g dotnet-script

Sample 1: Comparing File Sizes

$code = @"
using System;
using System.IO;

var file1 = Path.Combine(Directory.GetCurrentDirectory(), "fileA.txt");
var file2 = Path.Combine(Directory.GetCurrentDirectory(), "fileB.txt");

if (File.Exists(file1) && File.Exists(file2))
{
    var size1 = new FileInfo(file1).Length;
    var size2 = new FileInfo(file2).Length;
    Console.WriteLine($"{Path.GetFileName(file1)}: {size1} bytes");
    Console.WriteLine($"{Path.GetFileName(file2)}: {size2} bytes");
    Console.WriteLine(size1 > size2 ? "fileA is larger" : "fileB is larger");
}
else
{
    Console.WriteLine("One or both files do not exist.");
}
"@

$tmp = [IO.Path]::Combine($env:TEMP, "size_compare_$(Get-Random).csx")
$code | Out-File $tmp -Encoding UTF8
dotnet script $tmp
Remove-Item $tmp

Sample 2: Searching Files by Keyword

$code = @"
using System;
using System.IO;

var keyword = "report";
var root = Directory.GetCurrentDirectory();
var files = Directory.GetFiles(root, "*" + keyword + "*", SearchOption.AllDirectories);

if (files.Length == 0)
{
    Console.WriteLine("No matching files found.");
}
else
{
    foreach (var file in files)
    {
        Console.WriteLine(file);
    }
}
"@

$tmp = [IO.Path]::Combine($env:TEMP, "search_name_$(Get-Random).csx")
$code | Out-File $tmp -Encoding UTF8
dotnet script $tmp
Remove-Item $tmp

Sample 3: Outputting JSON with Newtonsoft.Json

$code = @"
#r "nuget: Newtonsoft.Json, 13.0.3"

using System;
using Newtonsoft.Json;

var person = new { Name = "Junya", Age = 26 };
var json = JsonConvert.SerializeObject(person, Formatting.Indented);
Console.WriteLine(json);
"@

$tmp = [IO.Path]::Combine($env:TEMP, "json_sample_$(Get-Random).csx")
$code | Out-File $tmp -Encoding UTF8
dotnet script $tmp
Remove-Item $tmp

Example output:

{
  "Name": "Sakaki",
  "Age": 99
}

Using External Libraries

To use third-party libraries in .csx scripts (such as Newtonsoft.Json), explicitly reference the package like this:

#r "nuget: Newtonsoft.Json, 13.0.3"
using Newtonsoft.Json;

Note: Do not use dotnet add package for .csx scripts. That command only applies to .csproj projects.


Summary

Invoking C# from PowerShell provides a clean and maintainable approach for writing automation scripts.
C# offers strong typing and a rich standard library, making it ideal for structured data and complex logic.
With dotnet-script, you can combine the power of PowerShell and C# to enhance your scripting workflow.

Accenture Japan (有志)

Discussion