🐶
PowerShellにも設定画面がほしい
何言ってやがんだとか思われるんでしょーがおっさんは本気です。
テキストで設定シコシコ書くのはさ、もーDOS時代にとっくに飽きてんだわ。おっさん。
ってわけで面倒事はPropertyGridに全部放り投げます。おいコラ、働けよ、計算機。
ちなみにPropertyGridってのはソフト屋なら某IDEで絶対見たことあるコレのコト
本題
いやもーここ数年弄ってない動的フォーム生成とか中々脳にキますな
function ShowSettingDialog {
param (
[Parameter(Mandatory = $true)] [string] $Title,
[Parameter(Mandatory = $true)] [System.Object] $Setting
)
begin {}
process {
# フォーム生成
$frmMain = New-Object System.Windows.Forms.Form -Property @{
Text = $Title # タイトル
StartPosition = 'CenterScreen' # 表示位置
Size = New-Object System.Drawing.Size(480,320)
Padding = New-Object System.Windows.Forms.Padding(5)
}
$tlpMain = New-Object System.Windows.Forms.TableLayoutPanel -Property @{
Dock = [System.Windows.Forms.DockStyle]::Fill
RowCount = 2
}
$pnlBody = New-Object System.Windows.Forms.Panel -Property @{
Dock = [System.Windows.Forms.DockStyle]::Fill
}
$grdProp = New-Object System.Windows.Forms.PropertyGrid -Property @{
Dock = [System.Windows.Forms.DockStyle]::Fill
SelectedObject = $Setting
}
$pnlTail = New-Object System.Windows.Forms.Panel -Property @{
Dock = [System.Windows.Forms.DockStyle]::Fill
}
$btnOK = New-Object System.Windows.Forms.Button -Property @{
Dock = [System.Windows.Forms.DockStyle]::Right
Size = New-Object System.Drawing.Size(128, 0) # ボタン巾のみ指定可能
Text = "OK"
UseVisualStyleBackColor = $true
DialogResult = [Windows.Forms.DialogResult]::OK
}
$btnCancel = New-Object System.Windows.Forms.Button -Property @{
Dock = [System.Windows.Forms.DockStyle]::Right
Size = New-Object System.Drawing.Size(128, 0) # ボタン巾のみ指定可能
Text = "Cancel"
UseVisualStyleBackColor = $true
DialogResult = [Windows.Forms.DialogResult]::Cancel
}
$null = $pnlBody.Controls.Add($grdProp)
$null = $pnlTail.Controls.Add($btnOK)
$null = $pnlTail.Controls.Add($btnCancel)
$null = $tlpMain.RowStyles.Add((New-Object System.Windows.Forms.RowStyle([System.Windows.Forms.SizeType]::Percent, 100)))
$null = $tlpMain.RowStyles.Add((New-Object System.Windows.Forms.RowStyle([System.Windows.Forms.SizeType]::Absolute, 50))) # ボタン高さはコレ
$null = $tlpMain.Controls.Add($pnlBody, 0, 0)
$null = $tlpMain.Controls.Add($pnlTail, 0, 1)
$null = $frmMain.Controls.Add($tlpMain)
# フォーム表示
$null = $frmMain.ShowDialog()
return $frmMain.DialogResult
}
end {}
}
使い方
で、まぁコレをこんな感じで使うんですわ
class AppSettings {
[System.ComponentModel.Description("名前")]
[string]$AppName
[int]$Version
[bool]$AutoUpdate
[string]$LogFilePath
[System.Diagnostics.SourceLevels]$LogLevel
}
$settings = [AppSettings]@{
AppName = "My Application"
Version = 1
AutoUpdate = $true
LogFilePath = "C:\app.log"
LogLevel = [System.Diagnostics.SourceLevels]::Information
}
$ret = ShowSettingDialog "Title" $settings
if ($ret -eq "OK") {
$settings
}
ってわけでコレが冒頭のアレになります
つまりクラス定義して変数ブチ込んであとは.Net様に全てお任せ
説明
データグリッドちゅーのはクラスメンバのプロパティに属性つけて
その指示に従って編集方法とかある程度変えられる代物です
でPowerShellから簡単に使える属性はこんな感じ
class AppSettings {
[System.ComponentModel.Description("説明文")]
[string]$AppName
[int]$Version
[bool]$AutoUpdate
# Enumは勝手にコンボになる
[System.Diagnostics.SourceLevels]$LogLevel
# 子要素に直接クラスがある場合は展開用の属性が必要
# でも実は子要素がクラスの配列の場合はこんなことしなくていい謎
[System.ComponentModel.TypeConverter(([System.ComponentModel.ExpandableObjectConverter]))]
[AppSettingsChild] Child
}
class AppSettingsChild {
[string]$Sample
}
他の属性はこの辺見てChatGPTなり何なりにお願いすれば大体オッケー
ただしカスタム属性は単発利用では苦労に見合わない感じなんで避けたほうがいいかと
無駄に努力してどーにかする方法を考えてみましたwww
ところでコイツ、現実的にはConvertFrom-Jsonで取ってきた設定を編集すんですが
何も考えずConvertFrom-Jsonしちゃうと値がPSCustomObjectにすり替わりますんで
ConvertFrom系使ったらそのまま突っ込まずにクラスへの変換が必要です
Discussion