ASP.NET Core Web APIで作成したAPIをIISに配置する
公開手順
APIサーバーを立ててIISをインストールする
APIサーバーをまずは作成します。APIをHyper-Vで活用したいというテーマがあるのでHyper-VでVMを作成し、APIサーバーとします。
名前はなんでも大丈夫です(僕はAPIcontrollerとしています。
スペックはWindows Serverが余裕で動くくらいでお願いします
- IISを導入する
サーバーマネージャーからIISを導入してください。
設定は全部デフォルトで大丈夫なはずです。
- IISを開いてサーバーを立てる
名前とかも適当で大丈夫です。
ただここでの設定ポートとAPIのほうのPropertiesにあるlaunchSettings.jsonにあるポートは統一してください。
ここまでできたら一旦準備完了です。
Visual Studioでプロジェクトを発行する
上のビルドタブから○○の発行があるのでそれをクリックします
フォルダを選択します
フォルダの場所は先ほどIISで作成したサイトのパスにします。
右上の発行を押せばそのフォルダにプロジェクトが発行されます。
ASP.NET Core Web APIで自作powershellモジュールを実行する
前の記事ではPowershellをASP.NET APIで動かすことが出来ました。
しかしこの書き方だと自作の関数やモジュールを動かすことができませんでした。
日本語ではこの情報がまったく見つからなかったので海外Webの海に飛び込み必死に調べ、ついに完全に理解したので記事にします。
動作環境
.NET 7.0
Microsoft.Powershell.SDK(7.3.2) NuGetからインストール
実際に自作モジュールを動かしてみよう
簡潔にコードから
今回実行する自作関数は別ホストにinvokeしてhostnameを取ってくるというものです。
前の記事から加えたところはinitialsessionstateという部分と、その中でPowershellの実行ポリシーを指定しているところですね。
// Use Custom Powershell Module in C# using System; using System.Diagnostics; using Microsoft.AspNetCore.Mvc; using System.Management.Automation; using System.Management.Automation.Runspaces; namespace test.Controllers //ここはプロジェクト名.controllerです { [Route("api/[controller]")] [ApiController] public class ValuesController : ControllerBase { //GET hostnameを取得 [HttpGet] [Route("gethost")] public void RunPowerShell() { var initialState = InitialSessionState.CreateDefault2(); initialState.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.Unrestricted; using var ps = PowerShell.Create(initialState); var results = ps.AddScript(@" Import-Module 'C:\Users\User\Documents\WindowsPowerShell\Modules\gethostname' gethostname ").Invoke(); //import-moduleのモジュール部分はフルパスで } } }
無事swaggerで200が帰ってきて、かつ画像の通り宛先ホストのhostnameが取得できました。
どうやらInitial Session Stateがキモみたいです
Initial Session Stateはセッションを作るときのコマンド、変数、モジュールなど、実行空間の特性を指定できると書いてあります。
前の記事ではどうやら実行ポリシーの関係上Import-Moduleを実行することができなかったようなので、
Initial Session Stateに実行ポリシーをUnrestrictedに指定することによって、自作モジュールを動かすことができたというわけです。
実行ポリシーが指定されていないと怒られます
InitialSessionState.CreateDefault2メソッドだとMicrosoft.PowerShell.Core モジュールがインポートされています。
InitialSessionState.CreateメソッドだとCoreモジュールもないまっさらな実行空間が作られます。
Runspaceは必須ではないみたいですが、なぜいらないのかあまりわかっていないので一応Runspaceを付けたいですね。。
あと好みの問題ですが、複数行のスクリプトよりもコマンドで実行させたいなと。。
改良してみた
// Use Custom Powershell Module in C# using System; using System.Diagnostics; using Microsoft.AspNetCore.Mvc; using System.Management.Automation; using System.Management.Automation.Runspaces; namespace test.Controllers //ここはプロジェクト名.controllerです { [Route("api/[controller]")] [ApiController] public class ValuesController : ControllerBase { //GET hostnameを取得 [HttpGet] [Route("gethost")] public void RunPowerShell() { var initialState = InitialSessionState.CreateDefault2(); initialState.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.Unrestricted; initialState.ImportPSModulesFromPath(@"C:\Users\User\Documents\WindowsPowerShell\Modules\hosttest"); Runspace runspace = RunspaceFactory.CreateRunspace(initialState); runspace.Open(); using var ps = PowerShell.Create(initialState); ps.Runspace = runspace; var results = ps.AddCommand("hostget").Invoke(); } } }
Initial Session Stateで実行ポリシーとモジュールも先に追加することによってImport-moduleコマンドをなくし、一応Runspaceを追加しています。
InitialSessionState.Createメソッドで一から使うコマンドの指定をするのもありかとは思いますが、一つ一つ作っていかないといけないのでCreateDefault2メソッドが最適だと思います。
とてもセキュリティが厳しい環境ならCreateメソッドを使うのはありだとは思います。。
まとめ
モジュール読み込みができるようになったことでAPIから自作関数を実行できるようになりました。
これでAPIから様々なPowershellの機能を短く便利に叩くことができますね!
一応二つの方法を記事にしましたが、好みですねここは。。
そして、モジュールさえも作らなくても一番目のコードのようにps.AddScript(@"")で囲むと複数行のスクリプトも実行できるのでそれでもいいと思います。。
ただ、様々な機能を含んだ複雑な実装になると管理も可読性も低くなるので、Powershellの部分はモジュール化してしまうのがおすすめでございます。
また情報があれば記事にします
ASP.NET Core Web APIでPowershellを実行する
この前C#でPowershellを動かせたので、ASP.NET Core Web APIでPowershellを動かしてみたという記事です
実際に作ってみよう
事前準備
Visual Studioを起動して新規プロジェクトの作成画面から、ASP.NET Core Web APIを選択します
ここはお好みで
ここでは.NET6.0にしましたが、7.0でもいいと思います(後述のnugetパッケージのバージョンに注意)
動作テストとnugetパッケージの追加
初期画面ですね、早速上にある再生ボタンみたいなボタンを押してみます。
実行されてAPIのテストができるSwaggerが開きました。動作確認したのでブラウザを閉じるかVisual Studioから停止させます。
次にパッケージを導入していきます。
依存関係のところでNuGetパッケージの管理を押します
たぶんOffline Packageが導入されているかと思うので右の歯車をクリックしてパッケージソースをオンラインから取ってこれるようにします。
パッケージソースを新規追加し、
https://api.nuget.org/v3/index.jsonを追加します
powershellと検索してMicrosoft.Powershell.SDKを見つけて入れます。
ここで重要なポイントです。
.Net 6.0にした場合は基本バージョン6.2.7を入れます。
7.x.xを入れる場合は.Net 7.0のプロジェクトにしてください。
(画像は後付けなので7.3.2が入ってます)
APIコントローラーの作成とコード作成
次にpowershellを実行するコントローラーを作成します。APIコントローラー(空)を選択しました。
特に指定がなければValuesControllerという名前で作成されます。
こんな感じが初期画面ですが、全部消して以下をコピペします
using Microsoft.AspNetCore.Mvc; using System.Management.Automation; using System.Management.Automation.Runspaces; namespace test.Controllers //ここはプロジェクト名.controllerです { [Route("api/[controller]")] [ApiController] public class ValuesController : ControllerBase { //GET hostnameを取得 [HttpGet] [Route("gethost")] public void RunPowerShell() { using (PowerShell ps = PowerShell.Create()) { var script = @" $res = invoke-command -scriptblock {hostname} | out-file C:\log\hostname.txt "; ps.AddScript(script); //PowerShellコマンドを実行 ps.Invoke(); } } } }
今回のAPIでは前の記事と違ってRunspaceを使わない簡単なpowershellの実行方法にしています。
中身はコンピューター名をC:\log\hostname.txtに入れるという動作になっています。
そのため、事前にC直下にlogファイルを作成してください。
(変数に入れたりinvoke-commandを使ったり無駄な部分がありますが検証で試した跡なので気にしないでください)
ちゃんとpowershellのパッケージを入れておけば動作すると思います
まとめ
このような感じで簡単にpowershellを実行できるAPIを作ることが出来ました。
活用方法としてはAPI用のサーバーの中にpowershellで運用に必要な機能を作ったモジュールを作成しておき、APIからinvoke-commandでAPI用サーバーへコマンドを投げることによって、
APIを駆使したWindows Server環境が作成できます。(不特定多数のユーザーが個別でVMを作ったり、消したり、メモリを変えたりなど)
ただこの前実行したrunspaceとの違いがよくわかっていないのでもうちょっと調べたいですね。。。
ただ.NET 6ではもうrunspaceinvokeが使えないっぽいです。。?これが後継ってことでいいのかな。。
また情報があれば記事にします
C#でPowershellを実行してみる

Hyper-VをAPIで管理することを目標にしながら、やっていこうかなと思います。
.NETでHyper-Vを管理する手法はどうやら二つあるようです。
- Hyper-V WMI Provider
- Powershellを実行する(system.management.automation)
今回は簡単そうなPowershellを実行する手法を試してみたメモです。
VBもC#もあんま知らないですが、C#のほうが役に立ちそうなのでC#でやります
C#でPowershellを呼び出す
PowershellはWindows上で実行するスクリプトとして最強なので正直この手法が楽だと思います
Get-VMなどの標準のコマンドレットや自作コマンドレットも実行できるので、C#でPowershellを実行するところは簡単にしておき、難しい処理はPowershellを作りこめばいいだけです。
Hyper-V WMI Providerの資料が全然ないのもこの方法で十分だからかもしれませんね。。。
とりあえずやってみましょう
参考にしたのはこちらのページ
developers.gmo.jp
このページの下部にあるサンプルコードをダウンロードしてVisual Studioで開きます
開いたらProgram.csの中身を見てみましょう
(.net frameworkが古いと言われるかもですが、推奨って書いてるやつ選択してください)
構造は
MainーーRunPowerShell | |ーRemotePowerShell | |ーRemotePipeline
的な感じになっており、Powershellを実行できるメソッドが三つあるようです。
33~35行目のコメントアウトを一つ外すことで三つのうちどれかを試せます。
(コメントアウト外すの忘れて時間無駄にしたので気を付けてください)
参考記事が最強すぎてこれ読むだけでも良いのですが
一つ一つのメソッドを一応簡単にかみ砕いてみました
RunPowershell
Mainで始めにアカウントやパスワード、実行するコマンドを入れておきます。
それで認証やinvoke-comanndなどにまとめて送信してくれるというものです。
Invoke-commandを使うのでWinRM接続設定をしておく必要があります
実行時にアクセスが拒否されました的なエラーが出たらTrustedHostsの設定が上手くいっていないかもしれません
strCmdの最初のTrustedHostsの部分をコメントアウトしましょう。
Powershellにて別でTrustedHostsの処理を実行しておきましょう
Set-Item WSMan:\localhost\Client\TrustedHosts -Value 実行元のIP -Force -ErrorAction Stop
minrootを変えたらWindowsサーバーが起動しなくなった
GPU-P vGPU付きVMを10台同時にベンチ回す (GPU-PV)
GPU-P (GPU-PV) 10台で回してみよう
最近GPU-Pのことを思い出しました。これからどんどんDaaS市場が発展していくと常々思うのでもう少し発展させてほしいと願っております。
NVIDIA GRIDや VMwareなどは発達しているみたいなんですけどね。。。Hyper-Vではうんともすんとも言わないですね。。
GPU-Pが次期Windows かWindows Serverで何か情報が来ることを祈りまして、10台ベンチを回します。
なぜ10台でベンチマークを回すか
以前の記事で3台同時に回したことがあるのですが、3台だと余裕だったので限界を知りたいという意味を込めて10台にします。10台がCPUもメモリもGPUも限界って感じでした。。。
どこかで理論上は32分割が限界だとか書いてたと思うのですが、さすがに32VM作れるのはサーバーにGPUぶちこむかRyzen Threadripperとかに24GBメモリ級のGPU詰め込むかですね。。。
でも仕組み的に32分割以上も出来そうな予感はするのですが、これ以上は個人的には出来なかったです。。。
10台のVMの作成方法
onissue.hatenablog.jp
これをぜひご参照ください。
今回のスペックも前の記事と同じでございます。
ベンチマークを回した結果
ベンチマークは簡単早いNovabenchで測定しました。
なんかすごい光景
気分はこんな感じですね。。。
結果は10台一応ちゃんと回りました!すごいえらい!
平均はこんな感じでした。まあこのスペックで10台回せただけでもよしとしましょう。
10台同時にYoutubeも再生してみた
Youtubeベンチもやってみましょう。結果はこんな感じでした。
(動画はトップにあった適当なの流してます)
https://onissue.hatenablog.jp/entry/2022/06/14/025607
結構ちゃんと再生できているのが驚きでした。。。
GPUなしだとザコCPUなので10台同時は難しかったと思います。
まあYoutubeはさっきのベンチマークよりかは動作が軽いとは思うのですが、それでもこの光景は高スペックVDIとしての可能性を秘めていて面白いですね。。。
ということなので、Azureばっかり頑張ってないで、こっちもよろしくお願いしますマイクロソフト様
(Azureのほうが儲かるんでしょうけど)
以上です。またGPU-Pについて記事にできるような情報が出てきたらうれしいですね