A la base le Framework .NET était destiné à faciliter le développement d’applications en fournissant une bibliothèque de classes sur laquelle la plupart des langages Microsoft s’appuyaient… Je pense notamment au C#, VB.NET ou encore le J#. C’est également le cas du PowerShell.
PowerShell est installé par défaut sur les systèmes d’exploitation les plus récents de Microsoft. Mais si vous l’avez installé vous-même, vous savez certainement remarqué que PowerShell nécessite au préalable l’installation du Framework .NET.
Cela s’explique simplement, les concepteurs de PowerShell se sont appuyés sur les librairies .NET pour développer les outils et lignes de commande « Cmdlet » disponibles en PowerShell.
PowerShell vous permet donc de manipuler un grand nombre d’objets définis dans la bibliothèque de classe du Framework .NET. Ainsi, pour utiliser une méthode statique d’une classe .NET, il vous suffit d’utiliser la syntaxe suivante :
[System.Reflecion.Assembly]::LoadWithPartialName('System.Windows.Forms')
Exemple simple, pour récupérer la date du jour.
En C#, si vous deviez afficher la date du jour, vous feriez probablement quelque-chose comme ça :
Console.WriteLine(System.DateTime.Now);
En Powershell, l’équivalent serait donc le suivant :
[System.DateTime]::Now
Ce que je souhaite aborder dans cet article, c’est qu’il est également possible de créer des interfaces graphiques en PowerShell, notamment grâce à l’assembly Windows Forms qui existe dans Microsoft .NET.
Vous allez voir qu’en dehors de la façon d’appeler ces méthodes, qui change, un peu, vous verrez que les noms des fonctions sont les mêmes.
Vous avez probablement déjà généré des GUI avec le designer de Visual Studio. Et bien, il est possible d’obtenir le même résultat en PowerShell. La différence, c’est qu’à l’heure actuelle, il n’existe (encore) pas de générateur visuel vous permettant de créer vos fenêtres en PowerShell… 🙂
Création d’une Windows Form en PowerShell
Avant de commencer, on va charger la bibliothèque Windows Form dans Powershell (non activée par défaut). Pour ce faire, on utilise la commande suivante :
[System.Reflecion.Assembly]::LoadWithPartialName('System.Windows.Forms')
C’est parti ! Créons notre première fenêtre au look and feel Windows… en PowerShell.
# Chargement des assemblies [void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") [void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") # Creation de la form principale $form = New-Object Windows.Forms.Form # Pour bloquer le resize du form et supprimer les icones Minimize and Maximize $form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedDialog $form.MaximizeBox = $False $form.MinimizeBox = $False # Choix du titre $form.Text = "Hello world... oui pas très innovant, je sais !" # Choix de la taille $form.Size = New-Object System.Drawing.Size(400,370) # Affichage de la Windows $form.ShowDialog()
Quelques points d’attention par rapport à ces quelques lignes de code :
- Si vous avez déjà fait du C#, vous verrez que le comportement est très proche (identique ?). Par exemple, si vous ne voyez rien à l’exécution du programme, c’est que vous avez probablement oublié d’appeler la méthode « ShowDialog » en fin de programme.
- La fonction « FormBorderStyle » avec le paramètre « FixedDialog » nous permet de fixer la dimension de la fenêtre. Elle ne pourra pas être redimensionnée manuellement.
- On supprime également les icônes qui permettraient de réduire/maximiser/réduire la fenêtre.
Voilà le résultat de ces quelques lignes.
Essayons maintenant d’ajouter quelques composants pour égayer un peu notre Form.
Je vous propose maintenant d’ajouter les composants suivants à notre fenêtre :
- Label
- TextBox
- Button
- CheckBox
- ProgressBar
Nous repartirons de l’exemple précédent.
Ajouter des composants
Une fois que nous avons défini et configuré notre fenêtre de base, nous allons dans un premier temps ajouter un bouton.
Pour ce faire, nous allons simplement déclarer un nouvel objet de type System.Windows.Forms.Button. La méthode Text nous permet de spécifier l’intitulé du bouton tandis que les méthodes Size et Location permettent respectivement de définir la taille du bouton en pixels ainsi que son emplacement sur la fenêtre.
NB : Le point (0;0) correspond au coin supérieur gauche de la fenêtre.
Globalement, ça ressemble à ça :
$button_ok = New-Object System.Windows.Forms.Button $button_ok.Text = "OK" $button_ok.Size = New-Object System.Drawing.Size(355,40) $button_ok.Location = New-Object System.Drawing.Size(20,230)
Ajoutons maintenant un autre composant basique… Ajoutons du texte via un Label. Vous allez voir que c »est tout aussi simple…
# Label May the force be with you $label_prez = New-Object System.Windows.Forms.Label $label_prez.Location = New-Object System.Drawing.Point(20,20) $label_prez.Size = New-Object System.Drawing.Size(100,20) $label_prez.Text = "May the force be with you... Choose your side : "
Je ne m’étendrai pas davantage sur les autres composants TextBox, CheckBox ou même la ProgressBar car le fonctionnement est le même et le code est identique.
Vous pourrez télécharger l’ensemble du code de ces 2 exemples à la fin de l’article.
Intéressons-nous maintenant à la gestion des événements qui vont notamment nous permettre d’interagir avec l’utilisateur. Par exemple, en cliquant sur des boutons.
Dans notre exemple, le bouton « Fermer » nous permettra de fermer la fenêtre en appelant la fonction méthode Close tandis que lorsque nous cliquerons sur le bouton « OK » nous modifierons le contenu d’un TextBox et nous remplirons la ProgressBar à 100%.
Côté code, c’est toujours aussi simple, voici ce que ça donne :
# Gestion event quand on clique sur le bouton Fermer $button_quit.Add_Click( { $form.Close(); }) # Gestion event quand on clique sur le bouton OK $button_ok.Add_Click( { $textbox_yoda.Text = 'Stop de cliquer partout !' $progress.Value = 100 })
Et bien sûr, visuellement, on obtient ceci :
En fin du programme, de la même façon que vous terminez par l’appel de la fonction ShowDialog pour afficher la Windows Form. Il est nécessaire d’insérer chacun des composants que vous avez créé à la Form principale via la commande suivante :
# Insertion du bouton Quitter dans la Windows Form principale $form.Controls.Add($button_quit) # Affichage de la Windows Form $form.ShowDialog()
Dans ces 2 exemples, j’ai regroupé chaque composant et sa configuration au même endroit. Idéalement, définissez tous vos composants dès le début et utilisez des sous-fonctions pour la bonne compréhension de votre script.
Vous pouvez télécharger les deux scripts en suivant le lien ci-dessous :
Si vous avez des questions, n’hésitez pas ! 🙂
Bonjour,
J’ai créé un PS1 avec Powershell ISE. Lorsque je l’exécute depuis ISE, aucun souci. En revanche, si j’exécute mon PS1 directement depuis l’explorateur Windows (ou depuis la console powershell.exe), mon interface est en mode « Windows 98 » (lol), à comprendre par exemple que mes boutons sont « plats ».
Une idée ? Une ligne de commande à ajouter dans mon script ? Mon chargement d’assembly qui n’est pas bon ?
J’utilise la ligne suivante :
Add-Type -AssemblyName System.Windows.Forms
Même si on voit souvent plutôt (testé mais ne change rien) :
[System.Reflection.Assembly]::LoadWithPartialName(« System.Windows.Forms »)
Pour info :
$PSVersionTable =
PSVersion 4.0
WSManStackVersion 3.0
SerializationVersion 1.1.0.1
CLRVersion 4.0.30319.18444
BuildVersion 6.3.9600.16406
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0}
PSRemotingProtocolVersion 2.2
Merci par avance 🙂
Hello Alexandre, je viens de re-tester de mon côté et je n’ai pas ce souci (et ce quelque soit la ligne de commande que je tape). As-tu d’autres spécificités dans ton code ? Ou d’autres choses que tu aurai ajouter ? Ou cela se produit avec les exemples basiques de l’article ? (tu peux partager une capture aussi, je suis curieux).
J’ai fini par trouver avec l’aide d’un collègue. En fait, j’ai dû ajouter la ligne suivante :
[System.Windows.Forms.Application]::EnableVisualStyles
Bien vu ! Et juste pour ma compréhension, je suppose que si tu dois ajouter ce paramètre en plus dans ton code c’est lié au fait que tu as désactivé les améliorations graphiques style Aero etc dans ta session Windows ? (sinon je vois pas trop pourquoi la nécessité d’ajouter ce paramètre en supplément).
Justement non, Aero est bien activé.Preuve en est, c’est qu’en exécutant mon PS1 par ISE (et sans cette ligne), j’ai bien les effets.
Je trouve un peu chiant ces différences d’interprétation entre ISE et le mode console (par contre je ne sais pas si c’est normal).