Powershell : création d'interfaces graphiques - troisième partie

Suite (et peut-être fin ?) des deux premiers articles concernant la création d'interfaces graphiques en Powershell ; après avoir vu les contrôles de base et les EventHandlers dans la première partie puis l'activation de contrôles ainsi que leur organisation au niveau spatial dans la seconde partie, je vais essayer d'aborder différemment les choses dans ce billet puisque nous allons développer ensemble une petite application récupérant les informations concernant les processeurs d'une station grâce à WMI et placer ces informations récupérées dans des contrôles. Cela est en quelque sorte une sorte de résumé ou de super-tutoriel par rapport à ce qui a été abordé précédemment, avec tout de même du nouveau contenu en termes de contrôles comme le DataGridView ou d'EventHandlers.

Tout d'abord, nous allons définir l'interface : une seule fenêtre, une TextBox pour saisir le nom de la station que nous souhaitons analyser, un Label pour indiquer le statut de la requête, 2 boutons (un pour lancer la requête, un deuxième pour effacer le tableau) et un DataGridView pour y renseigner les informations.

La Form :

$Form = New-Object System.Windows.Forms.Form
$Form.ClientSize = '400,450'
$Form.Text = "Mon UI en PS ep. III"
$Form.FormBorderStyle = 'Fixed3D'
$Form.MaximizeBox = $false

Le Label de statut :

$LabelStatus = New-Object System.Windows.Forms.Label
$LabelStatus.Location = New-Object System.Drawing.Point(20,20)
$LabelStatus.Text = "Saisir un nom de station."
$Form.controls.Add($LabelStatus)

La TextBox :

$TextBoxStation = New-Object System.Windows.Forms.TextBox
$TextBoxStation.Location = New-Object System.Drawing.Point(20,50)
$TextBoxStation.Width = 100
$TextBoxStation.TabIndex = 1
$Form.controls.Add($TextBoxStation)

Les Button pour déclencher la requête et vider le tableau :

$BoutonGetWMI = New-Object System.Windows.Forms.Button
$BoutonGetWMI.Location = New-Object System.Drawing.Point(150,50)
$BoutonGetWMI.Text = "Afficher les infos"
$BoutonGetWMI.Width = 100
$BoutonGetWMI.TabIndex = 2
$BoutonGetWMI.Enabled = $false
$BoutonClearTab = New-Object System.Windows.Forms.Button
$BoutonClearTab.Location = New-Object System.Drawing.Point(280,50)
$BoutonClearTab.Text = "Effacer le tableau"
$BoutonClearTab.Width = 100
$BoutonClearTab.TabIndex = 3
$BoutonClearTab.Enabled = $false
$Form.controls.AddRange(@($BoutonGetWMI,$BoutonClearTab))

Et enfin, le tableau, qui est représenté par l'objet DataGridView :

$DataGridViewCPU = New-Object System.Windows.Forms.DataGridView
$DataGridViewCPU.Location = New-Object System.Drawing.Point(20,80)
$DataGridViewCPU.Size = '360,290'
$DataGridViewCPU.ReadOnly = $true
$DataGridViewCPU.RowHeadersVisible = $false
$DataGridViewCPU.ColumnCount = 3
$DataGridViewCPU.Columns[0].Name = "CPU #"
$DataGridViewCPU.Columns[0].Width = 55
$DataGridViewCPU.Columns[1].Name = "Reference"
$DataGridViewCPU.Columns[1].Width = 140
$DataGridViewCPU.Columns[2].Name = "Freq. en MHz"
$DataGridViewCPU.Columns[2].Width = 140
$Form.controls.Add($DataGridViewCPU)

Les propriétés TabIndex permettent de définir l'ordre dans lequel les contrôles s'activent sur pression de la touche de tabulation. Avec ce code, l'interface est rendue comme telle :

L'interface de base une fois le code de l'UI terminé.
Concernant le DataGridView, plusieurs explications :
  • Cet objet fonctionne comme une collection d'autres objets : DataGridViewRow pour les lignes et DataGridViewColumn pour les colonnes.
  • La propriété ReadOnly permet d'éviter que l'utilisateur saisisse des informations dans les cases.
  • En fonction de ce que l'on souhaite afficher et de la liberté offerte à l'utilisateur, il est possible de bloquer le redimensionnement des colonnes, le tri, etc. Je vous renvoie vers la documentation Microsoft dont les liens sont en fin d'article pour plus d'informations.
Maintenant, il s'agit de coder les EventHandlers ; tout d'abord sur la TextBox, afin d'éviter que l'on lance la requête WMI si la TextBox est vide. Cet EventHandler se déclenche dès que son contenu est modifié : si le texte est vide, le bouton est grisé.

$TextBoxStation.Add_TextChanged({
if ($TextBoxStation.Text -eq "") { $BoutonGetWMI.Enabled = $false }
else { $BoutonGetWMI.Enabled = $true }

L'EventHandler pour vider le DataGridView. On efface toutes les lignes de celui-ci.

$BoutonClearTab.Add_Click({
$DataGridViewCPU.Rows.Clear()
$TextBoxStation.Enabled = $true
$TextBoxStation.Text = ""
   $BoutonClearTab.Enabled = $false })

Et enfin, l'EventHandler sur le bouton de récupération des informations ; c'est ici que l'essentiel du "vrai" code sera placé.

$BoutonGetWMI.Add_Click({
$CPUArray = Get-WmiObject win32_Processor -computername $TextBoxStation.Text
if ($?) {
foreach ($CPU in $CPUArray){
$DataGridViewCPU.Rows.Insert(0,$CPU.DeviceID,$CPU.Name,$CPU.MaxClockSpeed) }
$LabelStatus.Text = "Informations obtenues."
$BoutonGetWMI.Enabled = $false
$BoutonClearTab.Enabled = $true
$TextBoxStation.Enabled = $false

}
else { $LabelStatus.Text = "Erreur." }
})

Plusieurs choses concernant ces snippets :
  • En bleu, le code pour désactiver ou activer les boutons en fonction des besoins ; en faisant ceci, je m'assure que l'utilisateur ne peut pas lancer une requête et donc repeupler le tableau d'informations, je l'empêche également de modifier la saisie dans la TextBox. Ces contrôles sont réactivés lorsque le tableau est effacé.
  • En vert, cette condition permet de vérifier si la dernière instruction Powershell a renvoyé une erreur. Cela permet donc de réellement peupler le DataGridView si les objets ont bien été retournés ($? = $true) par la requête WMI ou de modifier le Label en conséquence sinon ($? = $false).
  • En orange, l'instruction permettant de remplir le DataGridView : bien qu'il soit possible d'ajouter les lignes une par une, nous allons dans notre cas les insérer. Afin de pouvoir ajouter un objet DataGridViewRow dans le DataGridView, il faut spécifier l'index ainsi que des valeurs pour les colonnes qui ont été déclarées. Avec cette commande, nous insérons donc tout en haut du tableau (index 0) les valeurs qui nous intéressent dans l'objet retourné par la requête WMI.
La requête n'a pas fonctionné.
La requête a fonctionné.

Par la suite, il est possible d'exploiter le contenu des cellules du DataGridView en appelant simplement les objets dont il est composé. Par exemple, on peut passer une boucle Foreach si l'on souhaite compter le nombre de CPU dont la fréquence est supérieure à 3000 MHz. En reprenant notre DataGridView, la troisième cellule de la ligne est celle de la fréquence, il faut donc analyser son contenu. Attention, les index débutent toujours par 0 et c'est un objet DataGridViewCell que nous allons appeler, ce qui nous intéresse pour la comparaison est sa propriété Value.

$ProcHauteFreq = 0
foreach ($Row in $DataGridViewCPU.Rows) {
if ($Row.Cells[2].Value -gt 3000) { $ProcHauteFreq++ }
}

On peut aussi par exemple exploiter le contenu simple d'une seule ou plusieurs cases. Dans cet exemple, le contenu de la case sélectionnée par l'utilisateur ira remplir le Label. Si plusieurs cellules sont sélectionnées, un tableau de DataGridViewCell sera retourné. Afin d'éviter une multiple sélection par l'utilisateur, on peut affecter la propriété Multiselect à False de cette manière :

$DataGridViewCPU.Multiselect = $False

$LabelStatus.Text = $DataGridViewCPU.SelectedCells.Value

Liens

Développement d'une UI en Powershell : première partie - deuxième partie
Documentation et références des classes : DataGridView - DataGridViewRow - DataGridViewColumn - DataGridViewCell
Lien pour marque-pages : Permaliens.

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.