Powershell – Créer de petites applications graphiques (GUI)

I. Présentation

Après de longues heures de labeur, vous avez achevé votre super script Powershell, mais il vous reste encore à le diffuser auprès de vos collaborateurs que l’austérité de la console va certainement rebuter. Que cela ne tienne, ajoutez-lui  une petite touche graphique et cela lui donnera instantanément un aspect plus appréciable 🙂

En matière d’interface graphique sous Powershell, vous avez le choix entre le traditionnel “Windows Forms” ou le “Windows Presentation Framework (alias WPF). Je vous propose d’aborder le premier choix, probablement moins “smart” mais à mon avis plus facile à mettre en œuvre (en terme d’outillage).

 

II. Explications

En langage Powershell, créer une interface graphique n’est pas chose facile et les techniciens comme moi, autrement dit les “non développeurs”, qui ne disposent que de très peu d’outils pour arriver à leurs fins.

Pour faire court, parmi les outils gratuits permettant de dessiner l’interface et générer le code correspondant, je n’ai retenu qu’un seul outil minimaliste mais efficace “PrimalForms CE”. Malheureusement, ce produit, proposé par Sapien n’est plus disponible depuis plusieurs années (probablement qu’il faisait de l’ombre à certains produits commerciaux 😀 ). Quoi qu’il en soit, il est toujours gratuit et fonctionnel, et au cas où vous auriez des difficultés à le trouver, je le mets à disposition ici ou  

III. Créer des applications

Après avoir installé ce petit outil, il vous suffit de lancer le raccourci “PrimalForms Community Edition“.

A. Créer le formulaire

Cliquez sur “New” pour créer votre nouvelle fenêtre d’application “Windows Forms”

Vue générale de ‘interface PrimalForms

A gauche, tous les “éléments de contrôle” qu’il suffit de sélectionner et déplacer vers le formulaire

A droite, toutes les “propriétés” de l’élément sélectionné. Les valeurs en gras, correspondent à des réglages modifiés par rapport à celles par défaut.

PrimalFormsCE : Détails des propriétés

Rien de très compliqué à l’usage, mais la richesse des informations proposées est quelque peu déroutante au début.

A droite, vous disposez également des options  évènementielles (handles) symbolisé par un éclair. Autrement dit, cette option permet de déclarer un événement sur le contrôle sélectionné, tel qu’un clic, une perte de focus, un changement d’état ou un autre événement.

PrimalFormsCE : Détails des événements

Si vous manquez d’inspiration pour le nommage de l’élément, double-cliquez simplement dans le champ de l’événement.

 

B. Sauvegardez votre projet

Enregistrez votre projet via le bouton “Save” ou “Save As“. Celui-ci portera l’extension “.pff” mais correspond à un format xml qui peut être consulté avec un simple éditeur de texte, tel que Notepad ++.

Fichier .pff (= xml)

Même si cela semble fastidieux au début, prenez l’habitude de nommer significativement les contrôles. Par exemple “btn_Quit”, “txt_Saisie” plutôt que “Button1, Textbox1…”

 

C. Générez le code Powershell

Ensuite, vous n’avez plus qu’à exporter ce formulaire graphique vers un fichier “.ps1” en cliquant sur le bouton “Export Powershell

A noter qu’il est également possible d’exporter ce code Powershell vers le presse papier.

 

D. Finaliser le code Powershell

C’est l’étape la plus délicate puisqu’elle consiste à renseigner le “véritable code” de votre application.

Et la gestion des éléments graphiques augmente très rapidement le nombre de lignes. Je vous conseille d’utiliser un éditeur tel que ISE v3 ou ultérieur afin de réduire [-] ou développer [+] les différentes régions de code.

Edition du code dans ISE

Le principal défaut est qu’il n’est pas possible de basculer entre la conception graphique et le code modifié. En cas de modification d’un élément graphique il faut jongler avec le presse papier pour modifier le code Powershell

 

IV. Exemple

Voici un petit exemple d’interface générée avec cet outil. Il s’agit d’un petit clavier de saisie de code PIN avec positionnement aléatoire des touches numériques (Histoire d’éviter le repérage des traces de doigts sur les écrans tactiles  😉 )

Exemple “PinCode.ps1”

Le code (un peu long n’est-ce pas ?) – mais quand on aime on ne compte pas 😀

#Generated Form Function

function GenerateForm {

########################################################################

# Code Generated By: SAPIEN Technologies PrimalForms (Community Edition) v1.0.9.0

# Generated On: 24/11/2016 18:46

# Generated By: Christophe

########################################################################



#region Import the Assemblies

[reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null

[reflection.assembly]::loadwithpartialname("System.Windows.Forms") | Out-Null

#endregion



#region Generated Form Objects

$PINCode = New-Object System.Windows.Forms.Form

$textBoxPIN = New-Object System.Windows.Forms.TextBox

$buttonRDM = New-Object System.Windows.Forms.Button

$buttonOK = New-Object System.Windows.Forms.Button

$buttonBK = New-Object System.Windows.Forms.Button

$button0 = New-Object System.Windows.Forms.Button

$button9 = New-Object System.Windows.Forms.Button

$button8 = New-Object System.Windows.Forms.Button

$button7 = New-Object System.Windows.Forms.Button

$button6 = New-Object System.Windows.Forms.Button

$button5 = New-Object System.Windows.Forms.Button

$button4 = New-Object System.Windows.Forms.Button

$button3 = New-Object System.Windows.Forms.Button

$button2 = New-Object System.Windows.Forms.Button

$button1 = New-Object System.Windows.Forms.Button

$InitialFormWindowState = New-Object System.Windows.Forms.FormWindowState

#endregion Generated Form Objects





#----------------------------------------------

#Generated Event Script Blocks

#----------------------------------------------

#Provide Custom Code for events specified in PrimalForms.







$buttonRDM_OnClick=

{

    Randomize-Buttons

}



$button0_OnClick=

{

   $textBoxPIN.Text = $textBoxPIN.Text + $button0.Text

}



$button1_OnClick=

{

   $textBoxPIN.Text = $textBoxPIN.Text + $button1.Text

}



$button2_OnClick=

{

   $textBoxPIN.Text = $textBoxPIN.Text + $button2.Text

}



$button3_OnClick=

{

   $textBoxPIN.Text = $textBoxPIN.Text + $button3.Text

}



$button4_Click=

{

   $textBoxPIN.Text = $textBoxPIN.Text + $button4.Text

}



$button5_OnClick=

{

   $textBoxPIN.Text = $textBoxPIN.Text + $button5.Text

}



$button6_OnClick=

{

   $textBoxPIN.Text = $textBoxPIN.Text + $button6.Text

}



$button7_OnClick=

{

   $textBoxPIN.Text = $textBoxPIN.Text + $button7.Text

}



$button8_OnClick=

{

   $textBoxPIN.Text = $textBoxPIN.Text + $button8.Text

}



$button9_OnClick=

{

   $textBoxPIN.Text = $textBoxPIN.Text + $button9.Text

}





$buttonBK_OnClick=

{

   $code = $textBoxPIN.Text

   if ($code.length -ne 0) {

     $textBoxPIN.Text = $code.Substring(0,$code.length -1)

   }

}



$buttonOK_OnClick=

{



  ####### !! CODE PIN SAISI

  Write-Host $textBoxPIN.Text



}




$OnLoadForm_StateCorrection=

{#Correct the initial state of the form to prevent the .Net maximized form issue

       $PINCode.WindowState = $InitialFormWindowState

   

    Randomize-Buttons

}



#----------------------------------------------

#region Generated Form Code

$PINCode.AutoScaleMode = 0

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Height = 192

$System_Drawing_Size.Width = 138

$PINCode.ClientSize = $System_Drawing_Size



$PINCode.FormBorderStyle = 'Fixed3D'

$PINCode.MaximizeBox = $false



$PINCode.DataBindings.DefaultDataSourceUpdateMode = 0

$PINCode.Name = "PINCode"

$PINCode.Text = "Code ?"

$PINCode.TransparencyKey = [System.Drawing.Color]::FromArgb(255,25,25,112)



$textBoxPIN.DataBindings.DefaultDataSourceUpdateMode = 0

$textBoxPIN.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",16,1,3,0)

$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 56

$System_Drawing_Point.Y = 10

$textBoxPIN.Location = $System_Drawing_Point

$textBoxPIN.Name = "textBoxPIN"

$textBoxPIN.PasswordChar = '*'

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Height = 32

$System_Drawing_Size.Width = 75

$textBoxPIN.Size = $System_Drawing_Size

$textBoxPIN.TabIndex = 14

$textBoxPIN.TextAlign = 2

$textBoxPIN.UseSystemPasswordChar = $True



$PINCode.Controls.Add($textBoxPIN)



$buttonRDM.BackColor = [System.Drawing.Color]::FromArgb(255,255,255,225)



$buttonRDM.DataBindings.DefaultDataSourceUpdateMode = 0

$buttonRDM.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",6,1,3,0)



$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 8

$System_Drawing_Point.Y = 10

$buttonRDM.Location = $System_Drawing_Point

$buttonRDM.Name = "buttonRDM"

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Height = 29

$System_Drawing_Size.Width = 38

$buttonRDM.Size = $System_Drawing_Size

$buttonRDM.TabIndex = 13

$buttonRDM.Text = "Rnd"

$buttonRDM.UseVisualStyleBackColor = $False

$buttonRDM.add_Click($buttonRDM_OnClick)



$PINCode.Controls.Add($buttonRDM)



$buttonOK.BackColor = [System.Drawing.Color]::FromArgb(255,166,202,240)



$buttonOK.DataBindings.DefaultDataSourceUpdateMode = 0

$buttonOK.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",8.25,1,3,0)



$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 8

$System_Drawing_Point.Y = 155

$buttonOK.Location = $System_Drawing_Point

$buttonOK.Name = "buttonOK"

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Height = 29

$System_Drawing_Size.Width = 36

$buttonOK.Size = $System_Drawing_Size

$buttonOK.TabIndex = 12

$buttonOK.Text = "OK"

$buttonOK.UseVisualStyleBackColor = $False

$buttonOK.add_Click($buttonOK_OnClick)



$PINCode.Controls.Add($buttonOK)



$buttonBK.BackColor = [System.Drawing.Color]::FromArgb(255,128,128,128)



$buttonBK.DataBindings.DefaultDataSourceUpdateMode = 0

$buttonBK.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",8.25,1,3,0)



$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 94

$System_Drawing_Point.Y = 155

$buttonBK.Location = $System_Drawing_Point

$buttonBK.Name = "buttonBK"

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Height = 29

$System_Drawing_Size.Width = 37

$buttonBK.Size = $System_Drawing_Size

$buttonBK.TabIndex = 11

$buttonBK.Text = "<X"

$buttonBK.UseVisualStyleBackColor = $False

$buttonBK.add_Click($buttonBK_OnClick)



$PINCode.Controls.Add($buttonBK)





$button0.DataBindings.DefaultDataSourceUpdateMode = 0

$button0.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",8.25,1,3,0)



$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 50

$System_Drawing_Point.Y = 155

$button0.Location = $System_Drawing_Point

$button0.Name = "button0"

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Height = 29

$System_Drawing_Size.Width = 38

$button0.Size = $System_Drawing_Size

$button0.TabIndex = 10

#$button0.Text = "0"

$button0.UseVisualStyleBackColor = $True

$button0.add_Click($button0_OnClick)



$PINCode.Controls.Add($button0)




$button9.DataBindings.DefaultDataSourceUpdateMode = 0

$button9.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",8.25,1,3,0)



$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 94

$System_Drawing_Point.Y = 121

$button9.Location = $System_Drawing_Point

$button9.Name = "button9"

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Height = 28

$System_Drawing_Size.Width = 37

$button9.Size = $System_Drawing_Size

$button9.TabIndex = 9

#$button9.Text = "9"

$button9.UseVisualStyleBackColor = $True

$button9.add_Click($button9_OnClick)



$PINCode.Controls.Add($button9)



$button8.DataBindings.DefaultDataSourceUpdateMode = 0

$button8.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",8.25,1,3,0)



$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 50

$System_Drawing_Point.Y = 120

$button8.Location = $System_Drawing_Point

$button8.Name = "button8"

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Height = 29

$System_Drawing_Size.Width = 38

$button8.Size = $System_Drawing_Size

$button8.TabIndex = 8

#$button8.Text = "8"

$button8.UseVisualStyleBackColor = $True

$button8.add_Click($button8_OnClick)



$PINCode.Controls.Add($button8)





$button7.DataBindings.DefaultDataSourceUpdateMode = 0

$button7.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",8.25,1,3,0)



$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 8

$System_Drawing_Point.Y = 120

$button7.Location = $System_Drawing_Point

$button7.Name = "button7"

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Height = 29

$System_Drawing_Size.Width = 37

$button7.Size = $System_Drawing_Size

$button7.TabIndex = 7

#$button7.Text = "7"

$button7.UseVisualStyleBackColor = $True

$button7.add_Click($button7_OnClick)



$PINCode.Controls.Add($button7)




$button6.DataBindings.DefaultDataSourceUpdateMode = 0

$button6.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",8.25,1,3,0)



$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 94

$System_Drawing_Point.Y = 86

$button6.Location = $System_Drawing_Point

$button6.Name = "button6"

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Height = 28

$System_Drawing_Size.Width = 37

$button6.Size = $System_Drawing_Size

$button6.TabIndex = 6

#$button6.Text = "6"

$button6.UseVisualStyleBackColor = $True

$button6.add_Click($button6_OnClick)



$PINCode.Controls.Add($button6)




$button5.DataBindings.DefaultDataSourceUpdateMode = 0

$button5.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",8.25,1,3,0)



$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 50

$System_Drawing_Point.Y = 86

$button5.Location = $System_Drawing_Point

$button5.Name = "button5"

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Height = 28

$System_Drawing_Size.Width = 38

$button5.Size = $System_Drawing_Size

$button5.TabIndex = 5

#$button5.Text = "5"

$button5.UseVisualStyleBackColor = $True

$button5.add_Click($button5_OnClick)



$PINCode.Controls.Add($button5)



$button4.DataBindings.DefaultDataSourceUpdateMode = 0

$button4.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",8.25,1,3,0)



$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 8

$System_Drawing_Point.Y = 86

$button4.Location = $System_Drawing_Point

$button4.Name = "button4"

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Height = 28

$System_Drawing_Size.Width = 38

$button4.Size = $System_Drawing_Size

$button4.TabIndex = 4

#$button4.Text = "4"

$button4.UseVisualStyleBackColor = $True

$button4.add_Click($button4_Click)



$PINCode.Controls.Add($button4)



$button3.DataBindings.DefaultDataSourceUpdateMode = 0

$button3.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",8.25,1,3,0)



$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 94

$System_Drawing_Point.Y = 52

$button3.Location = $System_Drawing_Point

$button3.Name = "button3"

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Height = 28

$System_Drawing_Size.Width = 37

$button3.Size = $System_Drawing_Size

$button3.TabIndex = 2

#$button3.Text = "3"

$button3.UseVisualStyleBackColor = $True

$button3.add_Click($button3_OnClick)



$PINCode.Controls.Add($button3)





$button2.DataBindings.DefaultDataSourceUpdateMode = 0

$button2.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",8.25,1,3,0)



$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 52

$System_Drawing_Point.Y = 52

$button2.Location = $System_Drawing_Point

$button2.Name = "button2"

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Height = 28

$System_Drawing_Size.Width = 36

$button2.Size = $System_Drawing_Size

$button2.TabIndex = 1

#$button2.Text = "2"

$button2.UseVisualStyleBackColor = $True

$button2.add_Click($button2_OnClick)



$PINCode.Controls.Add($button2)





$button1.DataBindings.DefaultDataSourceUpdateMode = 0

$button1.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",8.25,1,3,0)



$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 8

$System_Drawing_Point.Y = 52

$button1.Location = $System_Drawing_Point

$button1.Name = "button1"

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Height = 28

$System_Drawing_Size.Width = 38

$button1.Size = $System_Drawing_Size

$button1.TabIndex = 0

#$button1.Text = "1"

$button1.UseVisualStyleBackColor = $True

$button1.add_Click($button1_OnClick)



$PINCode.Controls.Add($button1)



#endregion Generated Form Code



#Save the initial state of the form

$InitialFormWindowState = $PINCode.WindowState

#Init the OnLoad event to correct the initial state of the form

$PINCode.add_Load($OnLoadForm_StateCorrection)

#Show the Form

$PINCode.ShowDialog()| Out-Null



} #End Function



function Randomize-Buttons {  #Randomize button values

  $buttonValue = 0..9 | Get-Random -Count 10

  $i = 0

  foreach ($Item in $buttonValue) {

   # Write-Output "Bouton[$i] = $($buttonValue[$i])"

    if ("button"+$i -eq $button0.Name) { $button0.Text = $($buttonValue[$i]) }

    if ("button"+$i -eq $button1.Name) { $button1.Text = $($buttonValue[$i]) }

    if ("button"+$i -eq $button2.Name) { $button2.Text = $($buttonValue[$i]) }

    if ("button"+$i -eq $button3.Name) { $button3.Text = $($buttonValue[$i]) }

    if ("button"+$i -eq $button4.Name) { $button4.Text = $($buttonValue[$i]) }

    if ("button"+$i -eq $button5.Name) { $button5.Text = $($buttonValue[$i]) }

    if ("button"+$i -eq $button6.Name) { $button6.Text = $($buttonValue[$i]) }

    if ("button"+$i -eq $button7.Name) { $button7.Text = $($buttonValue[$i]) }

    if ("button"+$i -eq $button8.Name) { $button8.Text = $($buttonValue[$i]) }

    if ("button"+$i -eq $button9.Name) { $button9.Text = $($buttonValue[$i]) }

   $i++

  }

}


#Call the Function

GenerateForm

 

Bons développements à tous.

Christophe

 

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

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