GUI Forms PowerShell
Windows PowerShell also supports building of Graphical User Interface (Forms). Many of the GUI administration tools available are scripted in PowerShell. There are many commercial and free tools available in the market, but let us see how to build a GUI form with PowerShell scripting.
Let us build a simple form now.
There are only three things required to launch a form from PowerShell:
- Load the System.Windows.Forms assembly;
- Create a new object of type system.windows.forms.form
- Call the ShowDialog() method on your new object.
Add-Type -AssemblyName System.Windows.Forms $Form = New-Object system.Windows.Forms.Form $Form.ShowDialog()
Save the above code and run the code. You can see a GUI Form like the following:

Let us add some more features to our form.
$Form.Height = 500 $Form.Width = 50
the above code will change the size of our form to 500 x 500.
$Form.BackColor = "Red" ## this will change the background color of the form to Red.
Now, let us add some more controls to our form.

Let is add some more functionality to our form.
Add-Type -AssemblyName System.Windows.Forms $Form = New-Object system.Windows.Forms.Form $Form.Height = 200 $Form.Width = 400 $Label1 = New-Object system.Windows.Forms.Label $Label1.text = "Click the button to get OS details" $Label1.AutoSize = $true $Label1.width = 25 $Label1.height = 10 $Label1.location = New-Object System.Drawing.Point(20,40) $Label1.Font = 'Microsoft Sans Serif,10' $TextBox1 = New-Object system.Windows.Forms.TextBox $TextBox1.multiline = $false $TextBox1.width = 300 $TextBox1.height = 20 $TextBox1.location = New-Object System.Drawing.Point(20,80) $TextBox1.Font = 'Microsoft Sans Serif,10' $Button1 = New-Object system.Windows.Forms.Button $Button1.text = "Click me!" $Button1.width = 80 $Button1.height = 30 $Button1.location = New-Object System.Drawing.Point(257,34) $Button1.Font = 'Microsoft Sans Serif,10' $Form.controls.AddRange(@($Label1,$TextBox1,$Button1)) $Button1.Add_Click({ $TextBox1.Text = (Get-WmiObject win32_operatingsystem).Caption; }) $Form.ShowDialog()
Save and run the code with PowerShell. On clicking the button, the textbox field will be updated with the Operating System Name of the current machine

Let is break down the code:
Create the form:
Add-Type -AssemblyName System.Windows.Forms ## adding the assembly
$Form = New-Object system.Windows.Forms.Form ## we are defining the form here
$Form.Height = 200 ## Form heoght
$Form.Width = 400 ## Form width
Create Label control:
$Label1 = New-Object system.Windows.Forms.Label ## Create Label
$Label1.text = “Click the button to get OS details” ## Label text that will be displayed
$Label1.width = 25 ## Label width
$Label1.height = 10 ## Label height
$Label1.location = New-Object System.Drawing.Point(20,40) ## Label Position
Create TextBox Control:
$TextBox1 = New-Object system.Windows.Forms.TextBox ## Create TextBox
$TextBox1.multiline = $false ## restricting the text to a single line. make this $true if you want to maek a multiline textbox and define number of lines.
$TextBox1.width = 300 ## width
$TextBox1.height = 20 ## height
$TextBox1.location = New-Object System.Drawing.Point(20,80) ## position
Create Button Control:
$Button1 = New-Object system.Windows.Forms.Button ## create Button control
$Button1.text = “Click me!” ## Button Text that will be displayed
$Button1.width = 80 ## Button width
$Button1.height = 30 ## Button height
$Button1.location = New-Object System.Drawing.Point(257,34) ## Button Position
Add Controls to the Form:
$Form.controls.AddRange(@($Label1,$TextBox1,$Button1)) ## this line will add the controls created in previous steps.
Add Button Click action:
$Button1.Add_Click({ $TextBox1.Text = (Get-WmiObject win32_operatingsystem).Caption; })
Show the Form:
$Form.ShowDialog()
Here are some of the GUI designer tools that you can try. I will add more in the future. You can try the following tools for building GUI utilities.
<# .NOTES -------------------------------------------------------------------------------- Powershell script to copy and install on remote servers Generated on: 8/11/2022 4:07 PM Generated by: Wintel -------------------------------------------------------------------------------- .DESCRIPTION GUI script to copy and install on remote servers #> #---------------------------------------------- # Form Function #---------------------------------------------- function Show-Install-Software_psf { #---------------------------------------------- #region Import the Assemblies #---------------------------------------------- [void][reflection.assembly]::Load('System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a') [void][reflection.assembly]::Load('System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a') [void][reflection.assembly]::Load('System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089') #endregion Import Assemblies #---------------------------------------------- # Form Objects #---------------------------------------------- [System.Windows.Forms.Application]::EnableVisualStyles() $form1 = New-Object 'System.Windows.Forms.Form' $richtextbox1 = New-Object 'System.Windows.Forms.RichTextBox' $buttonCopyAndInstall = New-Object 'System.Windows.Forms.Button' $textbox1 = New-Object 'System.Windows.Forms.TextBox' $labelSourceFolder = New-Object 'System.Windows.Forms.Label' $menustrip1 = New-Object 'System.Windows.Forms.MenuStrip' $folderbrowserdialog1 = New-Object 'System.Windows.Forms.FolderBrowserDialog' $loadServersToolStripMenuItem = New-Object 'System.Windows.Forms.ToolStripMenuItem' $openfiledialog1 = New-Object 'System.Windows.Forms.OpenFileDialog' $InitialFormWindowState = New-Object 'System.Windows.Forms.FormWindowState' #end Form Objects #---------------------------------------------- # User Script #---------------------------------------------- $form1_Load={ } $textbox1_Click={ #Select a folder if ($folderbrowserdialog1.ShowDialog() -eq 'OK') { $fpath = $folderbrowserdialog1.SelectedPath $textbox1.Text = $fpath if ($servers -and $textbox1.Text) { $buttonCopyAndInstall.Enabled = $true } $files = (Get-ChildItem $fpath | Where-Object { $_.Extension -in ".exe", ".ps1" }).Name foreach ($file in $files) { $combobox1.Items.Add($file) } } } $buttonCopyAndInstall_Click = { #compress selected folder $sourceFolder = $textbox1.Text $foldername = ($sourceFolder -split "\\")[-1] $zipname = "" 1 .. 10 | ForEach-Object { $zipname += "abcdefghijklmnopqrstuvwxyz".ToCharArray() | Get-Random } $script:destinationPath = $env:TEMP + "\" + $zipname + ".zip" Compress-Archive -Path $sourceFolder -DestinationPath $destinationPath $Server = "hv001" #Copy zip file to all servers foreach ($Server in $servers) { $script:successServers = @() $Error.Clear() $richtextbox1.AppendText("`nCopying to $server..") Start-Sleep -Seconds 1 try { Copy-Item $destinationPath ("\\" + $Server + "\C`$\Temp\") -ErrorAction Stop } catch {} if ($Error) { $richtextbox1.SelectionColor = 'Red'; $richtextbox1.AppendText("`nCopy Failed. " + $Error[0]); $richtextbox1.SelectionColor = 'Black'; } else { $richtextbox1.SelectionColor = 'Green'; $richtextbox1.AppendText("`nCopied successfully"); $successServers += $Server; $richtextbox1.SelectionColor = 'Black'; } Start-Sleep -Seconds 1 } #Remove zip file from temp after copy Remove-Item $destinationPath -Force foreach ($Server in $successServers) { Invoke-Command -ComputerName $Server -ScriptBlock { param ( [parameter(Mandatory = $true)] $zipfilePath, [parameter(Mandatory = $true)] $foldername ) #Expand zip archive Expand-Archive -Path $zipfilePath -DestinationPath C:\Temp -Force #Install software Set-Location ("C:\Temp\" + $foldername) .\Install.ps1 if ($LASTEXITCODE -ne 0) { $env:COMPUTERNAME + " - Installation Failed" } else { $env:COMPUTERNAME + " - Successfully Installed"; Set-Location "C:\Temp"; Remove-Item $zipfilePath -Force; Remove-Item $foldername -Recurse -Force; } } -ArgumentList ("C:\Temp\" + $zipname + ".zip"), $foldername -AsJob } Start-Sleep -Seconds 5 $richtextbox1.AppendText(((Get-Job| Receive-Job) | Out-String)) } $loadServersToolStripMenuItem_Click={ #Select a txt file $openfiledialog1.FileName = "" $openfiledialog1.Filter = "TXT file(*.txt)|*.txt" if ($openfiledialog1.ShowDialog() -eq 'OK') { $script:servers = Get-Content $openfiledialog1.FileName } if ($servers -and $textbox1.Text) { $buttonCopyAndInstall.Enabled = $true } } # --End User Script-- #---------------------------------------------- #region Events #---------------------------------------------- $Form_StateCorrection_Load= { #Correct the initial state of the form to prevent the .Net maximized form issue $form1.WindowState = $InitialFormWindowState } $Form_Cleanup_FormClosed= { #Remove all event handlers from the controls try { $buttonCopyAndInstall.remove_Click($buttonCopyAndInstall_Click) $textbox1.remove_Click($textbox1_Click) $form1.remove_Load($form1_Load) $loadServersToolStripMenuItem.remove_Click($loadServersToolStripMenuItem_Click) $form1.remove_Load($Form_StateCorrection_Load) $form1.remove_FormClosed($Form_Cleanup_FormClosed) } catch { Out-Null <# Prevent PSScriptAnalyzer warning #> } } #endregion Events #---------------------------------------------- #region Form Code #---------------------------------------------- $form1.SuspendLayout() $menustrip1.SuspendLayout() # # form1 # $form1.Controls.Add($richtextbox1) $form1.Controls.Add($buttonCopyAndInstall) $form1.Controls.Add($textbox1) $form1.Controls.Add($labelSourceFolder) $form1.Controls.Add($menustrip1) $form1.AutoScaleDimensions = New-Object System.Drawing.SizeF(10, 20) $form1.AutoScaleMode = 'Font' $form1.ClientSize = New-Object System.Drawing.Size(1150, 823) $form1.MainMenuStrip = $menustrip1 $form1.Margin = '8, 8, 8, 8' $form1.Name = 'form1' $form1.StartPosition = 'CenterScreen' $form1.Text = 'Form' $form1.add_Load($form1_Load) # # richtextbox1 # $richtextbox1.Anchor = 'Top, Bottom, Left, Right' $richtextbox1.Font = [System.Drawing.Font]::new('Consolas', '9') $richtextbox1.Location = New-Object System.Drawing.Point(14, 202) $richtextbox1.Margin = '5, 5, 5, 5' $richtextbox1.Name = 'richtextbox1' $richtextbox1.Size = New-Object System.Drawing.Size(1122, 607) $richtextbox1.TabIndex = 21 $richtextbox1.Text = '' # # buttonCopyAndInstall # $buttonCopyAndInstall.Enabled = $False $buttonCopyAndInstall.Location = New-Object System.Drawing.Point(402, 129) $buttonCopyAndInstall.Margin = '5, 5, 5, 5' $buttonCopyAndInstall.Name = 'buttonCopyAndInstall' $buttonCopyAndInstall.Size = New-Object System.Drawing.Size(182, 35) $buttonCopyAndInstall.TabIndex = 18 $buttonCopyAndInstall.Text = 'Copy and Install' $buttonCopyAndInstall.UseVisualStyleBackColor = $True $buttonCopyAndInstall.add_Click($buttonCopyAndInstall_Click) # # textbox1 # $textbox1.Location = New-Object System.Drawing.Point(164, 53) $textbox1.Margin = '5, 5, 5, 5' $textbox1.Name = 'textbox1' $textbox1.Size = New-Object System.Drawing.Size(442, 26) $textbox1.TabIndex = 16 $textbox1.add_Click($textbox1_Click) # # labelSourceFolder # $labelSourceFolder.AutoSize = $True $labelSourceFolder.Location = New-Object System.Drawing.Point(22, 56) $labelSourceFolder.Margin = '5, 0, 5, 0' $labelSourceFolder.Name = 'labelSourceFolder' $labelSourceFolder.Size = New-Object System.Drawing.Size(114, 20) $labelSourceFolder.TabIndex = 15 $labelSourceFolder.Text = 'Source Folder' # # menustrip1 # $menustrip1.ImageScalingSize = New-Object System.Drawing.Size(24, 24) [void]$menustrip1.Items.Add($loadServersToolStripMenuItem) $menustrip1.Location = New-Object System.Drawing.Point(0, 0) $menustrip1.Name = 'menustrip1' $menustrip1.Padding = '10, 3, 0, 3' $menustrip1.Size = New-Object System.Drawing.Size(1150, 35) $menustrip1.TabIndex = 20 $menustrip1.Text = 'menustrip1' # # folderbrowserdialog1 # # # loadServersToolStripMenuItem # $loadServersToolStripMenuItem.Name = 'loadServersToolStripMenuItem' $loadServersToolStripMenuItem.Size = New-Object System.Drawing.Size(125, 29) $loadServersToolStripMenuItem.Text = 'Load Servers' $loadServersToolStripMenuItem.add_Click($loadServersToolStripMenuItem_Click) # # openfiledialog1 # $openfiledialog1.FileName = 'openfiledialog1' $menustrip1.ResumeLayout() $form1.ResumeLayout() #endregion Generated Form Code #---------------------------------------------- #Save the initial state of the form $InitialFormWindowState = $form1.WindowState #Init the OnLoad event to correct the initial state of the form $form1.add_Load($Form_StateCorrection_Load) #Clean up the control events $form1.add_FormClosed($Form_Cleanup_FormClosed) #Show the Form return $form1.ShowDialog() } #End Function #Call the form Show-Install-Software_psf | Out-Null