Interface graphique PowerShell
Traduit de l'original en espagnol. Lire en espagnol
Exemple d’un script simple avec interface graphique.

Dans ce tutoriel, nous allons créer un script PowerShell qui propose une interface graphique (GUI) pour découper un fichier CSV en plusieurs fichiers selon un nombre de lignes donné.
Étape 1 : définir la fonction de découpage du fichier
D’abord, nous définissons une fonction qui se chargera de découper le fichier CSV. Elle a besoin du chemin source, du nombre maximal de lignes par fichier, du chemin de destination des fichiers produits et d’un modèle de nom de fichier.
function splitthefile($path_source_csv, $max_number_rows, $path_result_files, $filename) {
# Do something
}
Étape 2 : charger les assemblies nécessaires à la GUI
Ensuite, nous chargeons les bibliothèques .NET nécessaires pour créer la GUI.
Add-Type -AssemblyName PresentationFramework, PresentationCore, WindowsBase, System.Windows.Forms, System.Drawing
Étape 3 : personnaliser le thème et les icônes de la GUI
L’apparence de la GUI peut être personnalisée à l’aide de thèmes et d’icônes.
$ThemeFile = "$local_path\Themes\ExpressionDark.xaml"
$icon = "$local_path\Themes\favicon.ico"
Étape 4 : créer la mise en page de la GUI en XAML
Ensuite, nous définissons la mise en page de la GUI en XAML. Vous pouvez utiliser Visual Studio pour générer le XAML visuellement.
$inputXML = @"
<Window x:Class="csv.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:specialboackup"
mc:Ignorable="d"
Title="CSV Splitter" Height="300" Width="450" Icon="$icon">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="$ThemeFile" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Canvas HorizontalAlignment="Left" Height="251" Margin="10,10,0,0" VerticalAlignment="Top" Width="424">
<Button x:Name="get_source" Content="..." Canvas.Left="388" Canvas.Top="31" Width="26" Height="23" RenderTransformOrigin="-0.963,1.375"/>
<Button x:Name="split" Content="Split" Canvas.Left="299" Canvas.Top="214" Width="74" Height="26"/>
<TextBox x:Name="source" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" VerticalAlignment="Top" Width="363" Canvas.Left="10" Canvas.Top="31" RenderTransformOrigin="0.5,1"/>
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="Source CSV File" VerticalAlignment="Top" Canvas.Left="10" Canvas.Top="10" Width="348" Foreground="Black"/>
<Button x:Name="get_output" Content="..." Canvas.Left="388" Canvas.Top="82" Width="26" Height="23" RenderTransformOrigin="-0.963,1.375"/>
<TextBox x:Name="dest" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" VerticalAlignment="Top" Width="363" Canvas.Left="10" Canvas.Top="82" RenderTransformOrigin="0.5,1"/>
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="Output Folder" VerticalAlignment="Top" Canvas.Left="10" Canvas.Top="63" Width="348" Foreground="Black"/>
<TextBox x:Name="rows" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" VerticalAlignment="Top" Width="94" Canvas.Left="279" Canvas.Top="175" RenderTransformOrigin="0.5,1"/>
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="Number of rows per file" VerticalAlignment="Top" Canvas.Left="122" Canvas.Top="175" Width="137" Height="23" Foreground="Black"/>
<TextBox x:Name="filename" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" VerticalAlignment="Top" Width="94" Canvas.Left="279" Canvas.Top="138" RenderTransformOrigin="0.5,1"/>
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="New File Name" VerticalAlignment="Top" Canvas.Left="122" Canvas.Top="138" Width="137" Height="23" Foreground="Black"/>
</Canvas>
</Grid>
</Window>
"@
Étape 5 : analyser le XAML pour créer la GUI
La chaîne XAML est traitée pour créer les objets de la GUI.
$inputXML = $inputXML -replace 'mc:Ignorable="d"','' -replace "x:N",'N' -replace '^<Win.*', '<Window'
[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
[xml]$XAML = $inputXML
$reader=(New-Object System.Xml.XmlNodeReader $xaml)
try {
$Form=[Windows.Markup.XamlReader]::Load( $reader )
} catch {
Write-Warning "Unable to parse XML, with error: $($Error[0])`n Ensure that there are NO SelectionChanged properties (PowerShell cannot process them)"
throw
}
Étape 6 : lier les éléments de la GUI aux variables du script
Nous repérons tous les éléments nommés de la GUI et les lions à des variables du script.
$xaml.SelectNodes("//*[@Name]") | %{"trying item $($_.Name)";
try {Set-Variable -Name "WPF$($_.Name)" -Value $Form.FindName($_.Name) -ErrorAction Stop}
catch{throw}
}
Function Get-FormVariables {
if ($global:ReadmeDisplay -ne $true) {
Write-host "If you need to reference this display again, run Get- FormVariables" -ForegroundColor Yellow;$global:ReadmeDisplay=$true
}
write-host "Found the following interactable elements from our form" - ForegroundColor Cyan
get-variable WPF*
}
Étape 7 : définir les gestionnaires d’événements des clics sur les boutons
Des gestionnaires d’événements sont associés aux boutons de la GUI pour exécuter des actions lorsqu’on clique dessus.
$WPFget_source.Add_click({
$WPFsource.Text=Get-File
})
$WPFget_output.Add_click({
$WPFdest.Text=Get-Folder
})
$WPFsplit.Add_click({
$number_rows=$WPFrows.Text.Trim()
$path_source=$WPFsource.Text.Trim()
$path_dest=$WPFdest.Text.Trim()
$wshell = New-Object -ComObject Wscript.Shell
splitthefile -path_source_csv $path_source -max_number_rows $number_rows -path_result_files $path_dest -filename $WPFfilename.text.Trim()
$wshell.Popup("Split complete",0,"Messsage",0x1)
})
Étape 8 : afficher la GUI
Enfin, nous affichons la GUI et attendons que l’utilisateur interagisse avec elle.
$Form.ShowDialog() | out-null
Script PowerShell complet
Voici le script PowerShell complet, tel que décrit dans les étapes précédentes :
function splitthefile($path_source_csv, $max_number_rows, $path_result_files, $filename) {
# Do something
}
Add-Type -AssemblyName PresentationFramework, PresentationCore, WindowsBase, System.Windows.Forms, System.Drawing
$ThemeFile = "$local_path\Themes\ExpressionDark.xaml"
$icon = "$local_path\Themes\favicon.ico"
$inputXML = @"
<Window x:Class="csv.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:specialboackup"
mc:Ignorable="d"
Title="CSV Splitter" Height="300" Width="450" Icon="$icon">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="$ThemeFile" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Canvas HorizontalAlignment="Left" Height="251" Margin="10,10,0,0" VerticalAlignment="Top" Width="424">
<Button x:Name="get_source" Content="..." Canvas.Left="388" Canvas.Top="31" Width="26" Height="23" RenderTransformOrigin="-0.963,1.375"/>
<Button x:Name="split" Content="Split" Canvas.Left="299" Canvas.Top="214" Width="74" Height="26"/>
<TextBox x:Name="source" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" VerticalAlignment="Top" Width="363" Canvas.Left="10" Canvas.Top="31" RenderTransformOrigin="0.5,1"/>
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="Source CSV File" VerticalAlignment="Top" Canvas.Left="10" Canvas.Top="10" Width="348" Foreground="Black"/>
<Button x:Name="get_output" Content="..." Canvas.Left="388" Canvas.Top="82" Width="26" Height="23" RenderTransformOrigin="-0.963,1.375"/>
<TextBox x:Name="dest" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" VerticalAlignment="Top" Width="363" Canvas.Left="10" Canvas.Top="82" RenderTransformOrigin="0.5,1"/>
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="Output Folder" VerticalAlignment="Top" Canvas.Left="10" Canvas.Top="63" Width="348" Foreground="Black"/>
<TextBox x:Name="rows" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" VerticalAlignment="Top" Width="94" Canvas.Left="279" Canvas.Top="175" RenderTransformOrigin="0.5,1"/>
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="Number of rows per file" VerticalAlignment="Top" Canvas.Left="122" Canvas.Top="175" Width="137" Height="23" Foreground="Black"/>
<TextBox x:Name="filename" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" VerticalAlignment="Top" Width="94" Canvas.Left="279" Canvas.Top="138" RenderTransformOrigin="0.5,1"/>
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="New File Name" VerticalAlignment="Top" Canvas.Left="122" Canvas.Top="138" Width="137" Height="23" Foreground="Black"/>
</Canvas>
</Grid>
</Window>
"@
$inputXML = $inputXML -replace 'mc:Ignorable="d"','' -replace "x:N",'N' -replace '^<Win.*', '<Window'
[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
[xml]$XAML = $inputXML
#Read XAML
$reader=(New-Object System.Xml.XmlNodeReader $xaml)
try{
$Form=[Windows.Markup.XamlReader]::Load( $reader )
} catch {
Write-Warning "Unable to parse XML, with error: $($Error[0])`n Ensure that there are NO SelectionChanged properties (PowerShell cannot process them)"
throw
}
$xaml.SelectNodes("//*[@Name]") | %{"trying item $($_.Name)";
try {Set-Variable -Name "WPF$($_.Name)" -Value $Form.FindName($_.Name) -ErrorAction Stop}
catch{throw}
}
Function Get-FormVariables {
if ($global:ReadmeDisplay -ne $true) {
Write-host "If you need to reference this display again, run Get- FormVariables" -ForegroundColor Yellow;$global:ReadmeDisplay=$true
}
write-host "Found the following interactable elements from our form" - ForegroundColor Cyan
get-variable WPF*
}
$WPFget_source.Add_click({
$WPFsource.Text=Get-File
})
$WPFget_output.Add_click({
$WPFdest.Text=Get-Folder
})
$WPFsplit.Add_click({
$number_rows=$WPFrows.Text.Trim()
$path_source=$WPFsource.Text.Trim()
$path_dest=$WPFdest.Text.Trim()
$wshell = New-Object -ComObject Wscript.Shell
splitthefile -path_source_csv $path_source -max_number_rows $number_rows -path_result_files $path_dest -filename $WPFfilename.text.Trim()
$wshell.Popup("Split complete",0,"Messsage",0x1)
})
$Form.ShowDialog() | out-null
