- プログラミング
【.NET】PowerShell で GUI ツールを書いた話

こんにちは、IT 基盤本部の林です。
訳があり、PowerShell で GUI ツールを作成してみました。その感想の共有です。
前半は PowerShell 知らない方向けの事前解説です。
PowerShell とは?
PowerShell とは Microsoft 社が主体となりオープンソースで開発をおこなっているコマンドライン インターフェイスとそこで利用可能なスクリプト言語の名称です。
一般にシェルというと Linux でお馴染みの bash などを思い浮かべる方も多いと思います。実際 PowerShell も対話的なコマンド実行やスクリプトとしてファイルに記載された一連のコマンドを実行する機能を備えています。
ですが PowerShell の場合、シェル名乗っているくせにオブジェクト指向だったりします。マジかよ。
PowerShell の構文 (超基礎編)
シェル言語のくせにオブジェクト指向とは? という方は実際に見てみるのが早いです。最近の Windows には標準で PowerShell が入っています。まずは PowerShell を立ち上げて下記コマンドを実行してみてください。
Get-Date
読んで字のごとく現在の日時情報を取得するコマンドです。次にコマンドの実行結果を変数に格納してみます。
$now = Get-Date
実行結果は変数に格納されるため、ターミナルに実行結果は出力されません。そしてそのまま出力してみます。
$now
冒頭で直接 Get-Date のコマンドを出力させたときと同様の出力が確認できると思います。そして次はここから年だけ取り出してみましょう。
$now.Year
どうですか? 私は 2025 という結果を得ることができました。
……は? シェルなのにドット演算子?
「型」を持つシェル言語
種明かしをすると、PowerShell は入出力がオブジェクトとして行われます。型を持っています。そんな馬鹿な、なんですが前述に続けて下記コマンドを叩くことで型を確認することができます。
$now.GetType()

Get-Date コマンドの結果は「DateTime」という型のオブジェクトで返却されていることがわかります。実はこの DateTime 型は、.NET で標準的に提供されている型なんです。嘘やん。実際、Microsoft 社の .NET の解説サイトには DateTime 構造体に関するページが存在し、Year プロパティで年だけ数値として取り出せる旨が掲載されています。
(参考) DateTime.Year Property (System) | Microsoft Learn
https://learn.microsoft.com/ja-jp/dotnet/api/system.datetime.year?view=net-8.0#system-datetime-year
PowerShell は .NET をベースに開発されており、.NET の機能を利用することができます。同じく .NET 用のプログラミング言語である C# なんかで使える標準的な機能は理論上、大体利用可能ということです。
つまり……
GUI ツールを書けるシェル言語
まったく何を言っているんだ、という話なのですが、PowerShell は .NET で標準的に提供される機能は利用可能であるため、C# で GUI アプリが作れるということは理論上 PowerShell でも GUI アプリを作れるということになります。本当に何を言ってるんだ (困惑)
🤖「素直に C# 使えばいいのに……」
.NET で GUI アプリを作りたいなら C# を使えば楽になります。PowerShell は GUI のアプリケーション作成を想定した言語ではありません。だってシェル言語なのですから。C# を使いましょう。C# 大好き!
C# を使いたいのは山々なんですが、C# が使えない場面もあります。
それは我々の社内端末です。
exe ファイルを安易に出力できない時代
C# をはじめとするコンパイラ言語はソースファイルを exe にコンパイルしてから実行する必要があります。そして C# のコンパイラは (.NET Framework 時代のものですが) Windows には標準で入っております。以前は私は自分用ツールを作る際、メモ帳でサクッと C# のコードを書いてコンパイルしていました。
※最近は C# もスクリプト形式で実行できるようですが、自社環境では事情によりまだ使えず
ですが最近の我々の社内端末ではそうはいきません。exe ファイルが出力された瞬間にマルウェアとして検知されしまう恐れがあるためです。
昨今は油断するとすぐにランサムウェアなどの餌食になってしまう厳しいご時世です。いろんな企業が被害を受けているのをニュース等で聞くたび、私も震える一方です。
そのため、怪しい exe ファイルが PC 上に発生した途端に自動的にセキュリティ チームにアラートが上がってしまいます。私は C# のコンパイル操作の実行後、この誤検知で 2 回社内のセキュリティ担当の人にお世話になりました。セキュリティ チームの担当者さん、ご面倒をおかけしてしまい本当にすみません。

また、Python などをインストールすればスクリプトで GUI を作成できる可能性もありますが、勝手に Python の SDK とかインストールすると怒られる可能性があります。何よりも私が Python 扱えないし…… (こっちが本音)。
ということで PowerShell で GUI ツールを作成するという選択に至りました。
API のお試しコールを行うツール (Powered by PowerShell)
現在私は、AI の R&D チーム (いろいろトライ & エラーで開発を行うチーム) に所属しており、Microsoft Azure で提供される AI 関係の機能の検証をおこなっております。
対象となる AI 関係の機能のうちの 1 つにプロンプト フローというものがあります。プロンプト フローの詳細は別途記事に起こせればと思います。
このプロンプト フローはオリジナルのチャット bot などを作成する際に使える機能で、API 経由で呼び出すことも可能です。プロンプト フロー (というか自然言語で対話できる AI (LLM) 関連全般) の API はステートレスになっており、チャット形式で対話しようと思うと、ユーザーからのメッセージとこれまでの会話内容をセットで API のパラメータとして送信する必要があります。
毎度それまでの会話履歴を送る操作をそこら辺の API 検証ツールでやるのは少し面倒。
ということでプロンプト フローの API の検証を行うためのツールを PowerShell で作成しました。
ツール「Prompt Flow Executor」

上記が作成したツールの画面です。PowerShell で動いてます。動いちゃった。
PowerShell なので裏に別画面としていつもの黒い窓がいます。
以前ならこんなとち狂ったこと考えなかったのですが、AI が画面部分のコードを書いてくれるとなれば話は別です。
多少手直しはしましたが、ほとんど自社の生成 AI 利用基盤 "AIVolutionX" 製です。ごめんね、こんなことやらせて。LLM に申し訳なさを覚えます。
最初に UI だけを作らせました。そしてこの後、以前から使っていた非 GUI の PowerShell のコードを渡して、「さっき作ってくれた UI をこのスクリプトのロジックを使って実際に動くアプリケーションにしてくれ」みたいな雑なお願いの仕方ですが、ちゃんと理解してくれたようです。
下記は出力されたソースの冒頭部分です。こんな感じのコードがブロロロロロロロロと続きます。
Add-Type -AssemblyName System.Windows.Forms
# フォームの作成
$form = New-Object System.Windows.Forms.Form
$form.Text = "PromptFlow Executor"
$form.Size = New-Object System.Drawing.Size(500, 400)
# "Endpoint URL" ラベルとテキストボックス
$labelEndpointURL = New-Object System.Windows.Forms.Label
$labelEndpointURL.Text = "Endpoint URL"
$labelEndpointURL.Location = New-Object System.Drawing.Point(10, 10)
$form.Controls.Add($labelEndpointURL)
$textBoxEndpointURL = New-Object System.Windows.Forms.TextBox
$textBoxEndpointURL.Location = New-Object System.Drawing.Point(120, 10)
$textBoxEndpointURL.Size = New-Object System.Drawing.Size(350, 20)
$textBoxEndpointURL.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left -bor [System.Windows.Forms.AnchorStyles]::Right
$form.Controls.Add($textBoxEndpointURL)
全体でおよそ 200 行程度あります。GitHub の Gist かなにかにこの地獄のようなコードの全体を貼り付けたいところですね。
C# をお使いの方に UI の部分を簡単に説明すると C# で以前よく使われていた Windows Forms の機能を呼び出している、という内容です。WPF や MAUI を PowerShell で使おうとしたらどうなってしまうんだろう……恐ろしくて想像したくもないですね。
作ってみた (作ってもらった) 感想
PowerShell で GUI やりたい、というのはかなり特殊ケースだと思います。なのでこの記事のナレッジ (と言えるのか?) が役に立つかどうかも微妙……。
ですが頑張れば PowerShell でも GUI やれるにはやれます。やる必要はあるかは別として。
あと、やる内容によっては Windows に標準でバンドルされている PowerShell (PowerShell 5.x 系) では対応できないケースもあるかと思います。もしかすると、PowerShell 7.x 系を Microsoft のサイトから拾ってくる必要あるかもです。
基本的に PowerShell で GUI を扱うことはおすすめしません。(重要)
ありがとうございました。