はじめに
PowerShellは強力なスクリプト言語であり、システム管理や自動化に広く使用されています。しかし、C#のような他のプログラミング言語の機能を活用することで、さらに強力なスクリプトを作成することができそう。ここでは、PowerShellでC#のLINQ(Language Integrated Query)で使用する方法について調査しました。
LINQとは?
LINQは、C#や他の.NET言語で使用されるデータクエリ言語です。リストや配列などのコレクションに対して、簡潔で読みやすいクエリを記述することができます。
PowerShellでC#コードを実行する方法
PowerShellでは、Add-Typeコマンドレットを使用してC#コードを実行することができます。以下のサンプルコードでは、名前リストをフィルタリングするC#のメソッドをPowerShellから呼び出しています。
try {
# デバッグメッセージ
Write-Output "C#コードをテキストファイルに出力中..."
# デスクトップフォルダのパスを取得
$desktopPath = [Environment]::GetFolderPath([System.Environment+SpecialFolder]::Desktop)
$csFilePath = Join-Path -Path $desktopPath -ChildPath "LinqSample.cs"
# C#コードをテキストファイルに出力(UTF-8エンコーディングを指定)
$csCode = @"
using System;
using System.Collections.Generic;
using System.Linq;
public class LinqSample
{
// 名前リストをフィルタリングするメソッド
// names: フィルタリング対象の名前リスト
// filter: フィルタ文字列
public static List<string> FilterNames(List<string> names, string filter)
{
// LINQを使用してフィルタ文字列で始まる名前を抽出
return names.Where(name => name.StartsWith(filter)).ToList();
}
}
"@
Set-Content -Path $csFilePath -Value $csCode -Encoding UTF8
Write-Output "C#コードをテキストファイルに出力完了: $csFilePath"
# 型が既に登録済みか確認
$typeName = "LinqSample"
$typeExists = [AppDomain]::CurrentDomain.GetAssemblies() |
ForEach-Object { $_.GetTypes() } |
Where-Object { $_.FullName -eq $typeName }
if ($typeExists) {
# 型が既に登録されている場合のメッセージ
Write-Output "型 '$typeName' は既に登録されています。Add-Type をスキップします。"
Write-Output "理由: PowerShellでは、一度Add-Typeで追加された型は、同じセッション内で再度追加できません。"
Write-Output "対応策: 型を再定義するには、セッションを再起動する必要があります。"
Write-Output "この判定を入れている理由: PowerShell ISEなどのデバッグ実行環境で、同一セッション内でスクリプトをリランする際にエラーを防ぐためです。"
} else {
# C#コードをPowerShellに追加して実行(UTF-8エンコーディングを指定)
Write-Output "C#コードをPowerShellに追加中..."
$csCode = Get-Content -Path $csFilePath -Raw -Encoding UTF8
Add-Type -TypeDefinition $csCode -Language CSharp
Write-Output "C#コードをPowerShellに追加完了"
}
# サンプルデータ
$names = @("John", "Jane", "Mike", "Sara", "James")
Write-Output "サンプルデータ: $($names -join ', ')"
# フィルタ文字
$filter = "J"
Write-Output "フィルタ文字: $filter"
# C#のメソッドを呼び出してフィルタリング
Write-Output "C#のメソッドを呼び出してフィルタリング中..."
$filteredNames = [LinqSample]::FilterNames($names, $filter)
Write-Output "フィルタリング完了: $($filteredNames -join ', ')"
# 件数を確認
Write-Output "フィルタリングされた名前の件数: $($filteredNames.Count)"
# フィルタリングされた名前を1つずつ出力
Write-Output "フィルタリングされた名前を1つずつ出力:"
foreach ($name in $filteredNames) {
Write-Output $name
}
} catch {
Write-Output "エラーが発生しました: $_"
}
再読み込み時の注意点
PowerShellでは、一度Add-Typeで追加された型は、同じセッション内で再度追加することができません。そのため、スクリプトを再実行する際には、セッションを再起動する必要があります。これにより、型の再定義が可能になります。
まとめ
C#とのハイブリッドな処理はデバッグも大変で、実務で使えるかどうかはなんともですが、PowerShellでC#のLINQを活用することで、より強力なデータ操作が可能にはなります。


コメント