VisualStudioでPowerShell用GUIを作成する方法
PowerShellでGUIを使う記事を下記2件書きましたが、PowerShellのプログラムを動かすまでGUIを確認できず不便と思っていました。もしかしたら、VisualStudioを使うと、画面設計ができなかと思ったら、簡単に出来たので報告します。
自動生成されたXAMLを使いPowerShellプログラム作成
- 例えば下記のようにGUI部品を配置。
- 画面下部のXAML(文字列)を抜き出してPowerShellのプログラムを作成。
- ただし、一部の文字列は削除が必要(下記の黄色枠部分)。
- 下記がプログラムの例。「@'」と「'@」で囲まれた部分がXAML。
$ErrorActionPreference = "stop" Set-PSDebug -Strict Add-Type -AssemblyName PresentationFramework [xml]$xaml = @' <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <Label x:Name="label01" Content="名前" HorizontalAlignment="Left" Margin="15,26,0,0" VerticalAlignment="Top"/> <TextBox x:Name="textName" HorizontalAlignment="Left" Height="26" Margin="68,26,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="439"/> <Label x:Name="label02" Content="ふりがな" HorizontalAlignment="Left" Margin="15,57,0,0" VerticalAlignment="Top"/> <TextBox x:Name="textFurigana" HorizontalAlignment="Left" Height="26" Margin="68,57,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="439"/> <Label x:Name="label03" Content="性別" HorizontalAlignment="Left" Margin="15,88,0,0" VerticalAlignment="Top"/> <StackPanel x:Name="stackGender" HorizontalAlignment="Left" Height="26" Margin="68,88,0,0" VerticalAlignment="Top" Width="129" Orientation="Horizontal"> <RadioButton x:Name="radioButtonMale" Content="Male" Height="26" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="5,5,5,0"/> <RadioButton x:Name="radioButtonFemale" Content="Female" Height="26" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="5,5,5,0"/> </StackPanel> <Label x:Name="label04" Content="国籍" HorizontalAlignment="Left" Margin="15,119,0,0" VerticalAlignment="Top"/> <Label x:Name="label05" Content="年齢" HorizontalAlignment="Left" Margin="15,150,0,0" VerticalAlignment="Top"/> <TextBox x:Name="textAge" HorizontalAlignment="Left" Height="26" Margin="68,150,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="52"/> <ComboBox x:Name="comboBoxCountry" HorizontalAlignment="Left" Height="26" Margin="68,119,0,0" VerticalAlignment="Top" Width="439"/> <Button x:Name="buttonRegist" Content="登録" HorizontalAlignment="Left" Height="33" Margin="242,276,0,0" VerticalAlignment="Top" Width="48"/> <TextBlock x:Name="textBlock" HorizontalAlignment="Left" Height="90" Margin="15,181,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="492"/> </Grid> </Window> '@ $reader = New-Object System.Xml.XmlNodeReader $xaml $frm = [System.Windows.Markup.XamlReader]::Load($reader) $countries = "U.S.A China Japan Germany France England Russia".split(" ") $comboBoxCountry = $frm.FindName("comboBoxCountry") foreach ($country in $countries) { [void]$comboBoxCountry.Items.Add($country) } $textName = $frm.FindName("textName") $comboBoxCountry = $frm.FindName("comboBoxCountry") $textFurigana = $frm.FindName("textFurigana") $stackGender = $frm.FindName("stackGender") $textAge = $frm.FindName("textAge") $textBlock = $frm.FindName("textBlock") function getChecked($parent) { $checked = "" foreach ($child in $parent.Children) { if ($child.isChecked) { $checked += $child.Content } } return $checked } function regist { $name = $textName.Text $furigata = $textFurigana.Text $gender = getChecked $stackGender $country = $comboBoxCountry.SelectedValue $age = $textAge.Text $msg = "" $msg += "名前:" + $name + "`n" $msg += "ふりがな:" + $furigata + "`n" $msg += "性別:" + $gender + "`n" $msg += "国籍:" + $country + "`n" $msg += "年齢:" + $age + "`n" $textBlock.Text = $msg } $buttonRegist = $frm.FindName("buttonRegist") $buttonRegist.Add_Click({regist}) $result = $frm.ShowDialog()
- プログラム実行例。名前等を入力後、「登録」ボタンを押したところ。
あとがき
VisualStudioを使うと、PowerShellのGUIがとても簡単に設計できるので、ぜひ試してみてください。
おまけ
ListBoxやComboBoxは、PowerShellから簡単に項目を追加できるが、RadioButtonは簡単に追加できない。これはとても不便だが、次のようにプレースホルダを沢山書いておき、必要なものだけ表示するようにPowerShellで制御すれば、ある程度対応できることが分かった。ご参考まで。
- プログラム例:
$ErrorActionPreference = "stop" Set-PSDebug -Strict Add-Type -AssemblyName PresentationFramework [xml]$xaml = @' <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="xaml test #2" Width="170pt" Height="170pt"> <StackPanel> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center"> <StackPanel x:Name="country"> <RadioButton Content="PlaceHolder"></RadioButton> <RadioButton Content="PlaceHolder"></RadioButton> <RadioButton Content="PlaceHolder"></RadioButton> <RadioButton Content="PlaceHolder"></RadioButton> <RadioButton Content="PlaceHolder"></RadioButton> <RadioButton Content="PlaceHolder"></RadioButton> <RadioButton Content="PlaceHolder"></RadioButton> <RadioButton Content="PlaceHolder"></RadioButton> <RadioButton Content="PlaceHolder"></RadioButton> <RadioButton Content="PlaceHolder"></RadioButton> <RadioButton Content="PlaceHolder"></RadioButton> </StackPanel> <Label Content=" " FontSize="10pt"/> <StackPanel x:Name="fruits"> <RadioButton Content="PlaceHolder"></RadioButton> <RadioButton Content="PlaceHolder"></RadioButton> <RadioButton Content="PlaceHolder"></RadioButton> <RadioButton Content="PlaceHolder"></RadioButton> <RadioButton Content="PlaceHolder"></RadioButton> <RadioButton Content="PlaceHolder"></RadioButton> <RadioButton Content="PlaceHolder"></RadioButton> <RadioButton Content="PlaceHolder"></RadioButton> <RadioButton Content="PlaceHolder"></RadioButton> <RadioButton Content="PlaceHolder"></RadioButton> <RadioButton Content="PlaceHolder"></RadioButton> </StackPanel> </StackPanel> <Label x:Name="msg" Content=" " FontSize="10pt"/> <Button x:Name="btn" Content="Push Me" FontSize="10pt" /> </StackPanel> </Window> '@ $reader = New-Object System.Xml.XmlNodeReader $xaml $frm = [System.Windows.Markup.XamlReader]::Load($reader) $country = $frm.FindName("country") $fruits = $frm.FindName("fruits") $msg = $frm.FindName("msg") # 全てのRadioButtonを非表示にする foreach ($s in $country.Children) { $s.Visibility = "Collapsed" } # 全てのRadioButtonを非表示にする foreach ($b in $fruits.Children) { $b.Visibility = "Collapsed" } # RadioButtonのContentを設定し、表示する $countryList = "U.S.A China Japan Germany France England Russia".split(" ") $n = 0 $children = $country.Children foreach ($c in $countryList) { $radioButton = $children[$n] $radioButton.Content = $c $radioButton.Visibility = "Visible" $n += 1 } # RadioButtonのContentを設定し、表示する $fruitsList = "Apple Orange Grape".split(" ") $n = 0 $children = $fruits.Children foreach ($f in $fruitsList) { $radioButton = $children[$n] $radioButton.Content = $f $radioButton.Visibility = "Visible" $n += 1 } # 選択された項目を返す function getChecked($parent) { $checked = "" foreach ($child in $parent.Children) { if ($child.isChecked) { $checked += $child.Content } } return $checked } function clicked { $selectedCountry = getChecked $country $selectedFruits = getChecked $fruits $msg.content = "Country=" + $selectedCountry + "`n" + "Fruits=" + $selectedFruits } $btn = $frm.FindName("btn") $btn.Add_Click({clicked}) $result = $frm.ShowDialog()
- 実行例:
*1:それぞれの部品の意味は、別のサイト等で調べてください。