Créer une interface graphique WPF en PowerShell

Pour créer une interface graphique en PowerShell vous avez 2 choix : WPF (pour Windows Presentaton Foundation) ou bien Windows Forms.

Je vous avais déjà présenté un exemple de script PowerShell avec une GUI réalisée grâce aux Windows Forms en 2013 dans un précédent article. Je vous propose un exemple similaire mais cette fois-ci nous allons créer l’interface graphique avec WPF.

Création d’une interface graphique WPF simple

Dans un premier temps, nous allons voir comment créer une simple fenêtre en PowerShell grâce à WPF. Une fois réduit à l’essentiel le code ressemble à ceci :

Add-Type -AssemblyName PresentationFramework
$XML = @"
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            Title="WPF Windows" Height="480" Width="640">
            </Window>
"@

$FormXML = (New-Object System.Xml.XmlNodeReader $XML)
$Window = [Windows.Markup.XamlReader]::Load($FormXML)
$Window.ShowDialog()
Création d'une interface graphique simple WPF en PowerShell
Création d’une interface graphique simple WPF en PowerShell

Dans l’exemple ci-dessus, nous utilisons simplement la bibliothèque PresentationFramework qui existe dans .NET. Il reste ensuite à définir la taille de notre fenêtre en XAML et à l’appeler avec la fonction ShowDialog.

Ajoutons un élément sur notre fenêtre WPF

WPF propose différents éléments tels que des Button, Label et Textbox (et bien d’autres choses encore…) qui peuvent être utilisés pour ajouter des fonctionnalités à notre interface graphique.

Add-Type -AssemblyName PresentationFramework

$XML = @"
    <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    Title="WPF Window" Height="480" Width="640">
    <Button Name="MyButton" Width="80" Height="40" Content="OK" />
    </Window>
"@

$FormXML = (New-Object System.Xml.XmlNodeReader $XML)
$Window = [Windows.Markup.XamlReader]::Load($FormXML)
$Window.ShowDialog()
Création d'une interface graphique simple WPF en PowerShell avec un Bouton
Création d’une interface graphique simple WPF en PowerShell avec un Bouton

Voici un exemple de code qui permet en 1 ligne d’ajouter un bouton (qui ne fera rien dans un premier temps).

Evidemment, vous allez me dire – à juste titre, que configurer les éléments sur notre GUI à la main ce n’est pas très pratique… et vous aurez raison ! 😉

Heureusement, WPF et XAML étant des standards, nous allons pouvoir utiliser Visual Studio pour positionner graphiquement tous les éléments sur notre fenêtre ! Même si vous ne payez pas Visual Studio, vous pouvez télécharger et utiliser la version Community pour ce besoin.

Utiliser Visual Studio pour configurer notre GUI WPF

Pour ce faire, créez simplement un nouveau projet WPF.

Créez un projet de type WPF App dans Visual Studio
Créez un projet de type WPF App dans Visual Studio

Une fois le projet créé vous pourrez utiliser le Designer de Visual Studio pour créer et dessiner votre interface WPF.

Fonctionnement du Designer de Visual Studio
Fonctionnement du Designer de Visual Studio

Tous les éléments que vous pouvez utiliser sont (par défaut) à gauche de l’écran. Pour chaque élément, vous pouvez accéder aux options de l’objet en bas à droite (pour changer le texte ou les comportements). Le code est ensuite généré automatiquement dans la partie en bas sous votre interface graphique en XAML. 🙂

Intégrer le code du Designer dans votre script PowerShell

Il ne vous reste plus qu’à copier-coller le contenu de votre code XAML (en bas – dans Visual Studio) dans votre script PowerShell et remplacer le contenu de la variable $XML.

Par défaut, le code est le suivant dans mon cas :

<Window x:Class="WpfApp1.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:WpfApp1"
        mc:Ignorable="d"
        Title="Test Connection Window" Height="121.071" Width="460" ResizeMode="NoResize">

    <Grid Background="#FFC1C3CB">
        <Button Name="button_Connect" Content="Close" HorizontalAlignment="Left" Margin="327,10,0,0" VerticalAlignment="Top" Width="100" Height="54"/>
        <Label Name="Label_Email" Content="Your email:" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="130"/>
        <TextBox Name="TextBox_Email" HorizontalAlignment="Left" Height="23" Margin="145,10,0,0" TextWrapping="Wrap" Text="youremail@domain.fr" VerticalAlignment="Top" Width="160"/>
        <Label Name="Label_Password" Content="Your Password" HorizontalAlignment="Left" Margin="10,41,0,0" VerticalAlignment="Top" Width="130"/>
        <PasswordBox Name="TextBox_Password" HorizontalAlignment="Left" Margin="145,41,0,0" VerticalAlignment="Top" Width="160" Height="23"/>
    </Grid>
</Window>

Mais pour que ça marche, vous devez absolument modifier ce code pour qu’il fonctionne dans votre script PowerShell. Dans le code XAML, dans la partie commençant par Window retirez simplement les lignes inutiles.

Au final, dans mon cas, cela donne ça :

Add-Type -AssemblyName PresentationFramework

$XML = @"
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        Title="Test Connection Window" Height="121.071" Width="460" ResizeMode="NoResize">

    <Grid Background="#FFC1C3CB">
        <Button Name="button_Connect" Content="Close" HorizontalAlignment="Left" Margin="327,10,0,0" VerticalAlignment="Top" Width="100" Height="54"/>
        <Label Name="Label_Email" Content="Your email:" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="130"/>
        <TextBox Name="TextBox_Email" HorizontalAlignment="Left" Height="23" Margin="145,10,0,0" TextWrapping="Wrap" Text="youremail@domain.fr" VerticalAlignment="Top" Width="160"/>
        <Label Name="Label_Password" Content="Your Password" HorizontalAlignment="Left" Margin="10,41,0,0" VerticalAlignment="Top" Width="130"/>
        <PasswordBox Name="TextBox_Password" HorizontalAlignment="Left" Margin="145,41,0,0" VerticalAlignment="Top" Width="160" Height="23"/>
    </Grid>
</Window>
"@

$FormXML = (New-Object System.Xml.XmlNodeReader $XML)
$Window = [Windows.Markup.XamlReader]::Load($FormXML)
$Window.ShowDialog()
Intégrer le code du Designer à votre script PowerShell
Intégrer le code du Designer à votre script PowerShell

Désormais, il vous suffit de conserver votre projet Visual Studio séparément. Vous pourrez alors facilement configurer votre interface graphique WPF depuis le Designer… et ensuite copier-coller les changements dans votre script PowerShell.

Gérer un événement sur le click du Bouton

Il y a encore plein de possibilités… Mais dans cette dernière étape, nous allons voir ensemble comment gérer un événement de type click sur le Bouton Close. Vous l’aurez compris, je souhaite donc que lorsque l’on clique sur le bouton Close la fenêtre se ferme. 😉

Cette fois-ci le code ressemblera à ceci :

Add-Type -AssemblyName PresentationFramework

$XML = @"
        <Window 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        x:Name="Window" Title="Test Connection Window" Height="121.071" Width="460" ResizeMode="NoResize">

    <Grid x:Name="LayoutRoot" Background="#FFC1C3CB">
        <Button x:Name="Close" Content="Close" HorizontalAlignment="Left" Margin="327,10,0,0" VerticalAlignment="Top" Width="100" Height="54" />
        <Label Name="Label_Email" Content="Your email:" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="130"/>
        <TextBox Name="TextBox_Email" HorizontalAlignment="Left" Height="23" Margin="145,10,0,0" TextWrapping="Wrap" Text="youremail@domain.fr" VerticalAlignment="Top" Width="160"/>
        <Label Name="Label_Password" Content="Your Password" HorizontalAlignment="Left" Margin="10,41,0,0" VerticalAlignment="Top" Width="130"/>
        <PasswordBox Name="TextBox_Password" HorizontalAlignment="Left" Margin="145,41,0,0" VerticalAlignment="Top" Width="160" Height="23"/>
    </Grid>
</Window>
"@

$FormXML = (New-Object System.Xml.XmlNodeReader $XML)
$Window = [Windows.Markup.XamlReader]::Load($FormXML)

$Window.FindName("Close").add_click({ 
    $Window.Close() 
}) 

$Window.ShowDialog() | Out-Null
Gestion d'un événement de Click
Gestion d’un événement de Click

J’attire votre attention sur les zones en rouge dans le screenshot ci-dessus. Cela représente les zones qui doivent modifiées pour que votre événement soit correctement géré et que vous n’ayez pas de message d’erreur ou d’avertissement au moment de l’exécution.

Téléchargements

Voilà, c’est terminé pour ce tuto.

Il ne vous reste plus qu’à créer de nouveaux éléments via le Designer pour améliorer votre interface graphique puis à gérer d’autres événements. 🙂

Comme d’habitude, je vous laisse une copie des scripts en téléchargement en suivant ce lien. Cela vous permettra de faire vos propres tests. 😉