PowershellのユーザーフォームをVisualStudioで手軽に作成する

使ったもの、バージョン等
powershell 5.1
powershell ISE
Visual Studio 2017

#概要
 PowerShellのGUIをサイズなど手探りで作成するのが手間だったので、Visual Studio のVB用のWindowsフォームを利用して作成して、それをPowerShellの文法に直して（といってもほぼ文字置換のみですが）流用するという邪道的な方法です。
どちらも.GUIはNETFrameworkを使用するので文法はあまり変わらないんじゃないかと思ってやってみたら、本当に簡単にできました。
　私はVBは全く知りません。PowerShellも大してできるわけじゃないんですが。
　そんな人でもPowerShell用のGUIが簡単に作れますよというメモです。
　なぜVBで作ったものをわざわざPowerShellに書き換えるかというと、もうそれは会社のPCがインストール禁止,自作exe禁止だからという点に尽きます。
<img width="900" alt="2020-04-22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622636/d7075590-901d-cc37-ec74-19025fed787f.png"><img width="900" alt="2020-04-22 (1).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622636/429d2d1b-fcb0-c9bd-7977-636ed6ee43fa.png">
　まずはVisualStudioで新規作成→プロジェクト→
左でVisualBasicを選択→Windowsフォームアプリケーション（.NET Framework）→OK

<img width="900" alt="2020-04-22 (2).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622636/54bbabc2-7655-4fb0-abb4-c52c65706fdc.png">

ツールボックスが表示されていなかったら、表示→ツールボックスで表示されます。
<img width="900" alt="2020-04-22 (3).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622636/23e544ba-d9d9-6b73-4937-522d1702726f.png">

各ツールを配置します。配置や修正の方法はVBAとほとんど同じですので割愛します。
<img width="900" alt="2020-04-22 (4).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622636/40b15453-b13f-2c5b-70fb-66edc39f6deb.png">
できました。
タブの「Form1.vb(デザイン)」タブから「Form1Designer.vb」タブに移動します。
<img width="900" alt="2020-04-22 (5).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622636/0956d1ae-88cb-478a-9bdf-3870aae24c00.png">
このコードを上から下まで全コピーしてPowerShell ISEに連れてきます（下で削除している先頭部分、末尾部分を除いてコピーでもOK）。

先頭の
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _から Private Sub InitializeComponent()まで削除します
<img width="900" alt="2020-04-22 (6).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622636/b97d9e1e-ad0e-0f6b-5c52-a692fc5b3a57.png">

末尾の
End Sub からEnd Clas　までのfriendまわりも削除します
<img width="900" alt="2020-04-22 (7).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622636/a2567f52-1547-fc6c-9963-71024d009ae4.png">

#置換作業
PowerShell ISEの編集→スクリプト内で置換
で
<img width="900" alt="2020-04-22 (8).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622636/7a03ef9f-23e3-9375-eccc-83dfe5ba7198.png">
コメントアウトの「'」をPowerShell用に「#」に全置換
Single指定の「!」も「」に置換して消す
「True」を「＄True」
「False」を「＄False」に全置換（注：＄は半角）
インスタンス生成の「New」を「New-Object」に置換
インスタンス生成時のコンストラクタの「（）」を「」に置換して消します。消すのは最初のインスタンス生成の部分だけで、Me.SuspendLayout()以降は消してはいけません。
　引数なしメソッドの（）は消さないように。繰り返しになりますが、特にインスタンス生成直後のMe.SuspendLayout()の()からは消さないでください。
<img width="900" alt="2020-04-22 (9).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622636/ac562b17-c268-d482-7443-1f54faa6c5de.png">

最後に「Me.」を「＄」に置換するのですが、Form　Classを削除している関係で、インスタンス生成直後のMe.SuspendLayout()と最後の#Form1ブロックの左辺はフォームの変数（今回は＄form）にする必要があります。
　先に#Form1ブロックの左辺を「Me.」から「＄form.」に置換して、残りすべてを「Me.」を「$」に置換します。
　これで置換作業は終了です。
<img width="900" alt="2020-04-22 (13).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622636/0c26e0c8-bf48-413b-f76f-9234953c99b8.png">
先に#Form1ブロックの左辺を「Me.」から「＄form.」に置換
その後「Me.」を「＄」に全置換するのがよいと思います。
だいぶそれらしくなってきました。

#アセンブリのロード
使用されているアセンブリを確認して、今回は
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.drawing
の２つをロードします。
また、Form　Classを削除しているので、先ほど置き換えた変数名でフォームを定義します。
$form = New-Object  System.Windows.Form<img width="900" alt="2020-04-22 (14).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622636/a9d92e8d-94e8-4e33-f49c-ffba1dd8682a.png">

#static関係を修正,仕上げ



<img width="900" alt="2020-04-22 (17).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622636/68fe7f93-3bd4-6228-14b1-9c5c9f99dc9f.png">


　System.Windows.Forms.AutoScaleMode.Font
→
　[System.Windows.Forms.AutoScaleMode]::Font



<img width="900" alt="2020-04-22 (18).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622636/374e68d1-575e-37c0-cf73-dff80438a702.png">



System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(128, Byte)
→
[System.Drawing.FontStyle]::Regular,[ System.Drawing.GraphicsUnit]::Point,128

CTypeは型変換で型をバイトにしていますが、１２８の数値自体は変わりません。

そしていよいよ末尾に ＄result = ＄form.ShowDialog()を追加すると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622636/f590a5e1-c960-6a65-ec03-4c5f17b89b57.png)
表示されました。

　そして、キーボードでユーザーフォームを操作しやすくするために、タブクリックで指定される順序「TabIndex」の値を操作します。そのままだとユーザーフォームで作った順番で、しかもラベルが含まれてしまいます。最初がTabIndex = 0となり、1からではないのでご注意ください。
　これで、とりあえずフォームは完成です。

　もちろん、ここから各ボタンのイベント登録、記載の重複等の整理が要りますが、とりあえずフォームを手探りで作らなくていいので、便利だと思います。

　5/15追記　()の置換部分とCTypeの変換部分