The command-line interface is one of the major drawbacks of PowerShell scripts when used by users (not sysadmins or programmers). Script results are displayed in the PowerShell CLI console, which is not always convenient for end-users. In order to make your scripts more user-friendly, you can easily add a simple graphical user interface (GUI) to them.
You can create graphical elements for your PowerShell scripts by using .NET Framework objects in Windows PowerShell. Commonly used libraries are .NET Windows Forms (WinForms) or Windows Presentation Foundation (WPF).
Create a PowerShell GUI using the WinForms class
In this example, we use the System.Windows.Forms class to create a simple GUI for a PowerShell script. The script displays the last password change date for the selected Active Directory user.
Hint. You can edit your PowerShell scripts using the built-in PowerShell ISE or install the advanced Visual Studio Code (VScode).
Open your PowerShell code editor and create a new .ps1 file.
Create Windows Form with PowerShell
You must load the .NET System.Windows.Forms class into your PowerShell session to use WinForms objects.
Add-Type -assembly System.Windows.Forms
Then create the screen form (window) that will contain the graphical elements:
$main_form = New-Object System.Windows.Forms.Form
Set the title and size (width and height) of the form:
$main_form.Text ='GUI for my PoSh script' $main_form.Width = 600 $main_form.Height = 400
Use the AutoSize property to automatically stretch the form if the elements on the form are outside the form boundaries:
$main_form.AutoSize = $true
Now you can display the form on the screen:
$main_form.ShowDialog()
How to Add Common Dialog Control Items to a PowerShell Form?
As you can see, a blank graphical form is displayed. To add graphical dialog and control elements to it, add the following code before the last line ($main_form.ShowDialog()).
Create a label element on the form (displays custom text):
$Label = New-Object System.Windows.Forms.Label $Label.Text = "AD users" $Label.Location = New-Object System.Drawing.Point(0,10) $Label.AutoSize = $true $main_form.Controls.Add($Label)
The relative coordinates of the graphic form where the element is to be displayed are specified using the Location property. System.Drawing.Point objects are used to set the size and position of controls. Two coordinates are passed as arguments: the first is horizontal and the second is a vertical coordinate. The origin of the coordinates is in the upper left corner.
Let’s create a drop-down list containing a list of user accounts from the Active Directory domain. You can use the Get-ADuser cmdlet to get the list of AD users (from the PowerShell Active Directory module):
$ComboBox = New-Object System.Windows.Forms.ComboBox $ComboBox.Width = 300 $Users = get-aduser -filter * -Properties SamAccountName Foreach ($User in $Users) { $ComboBox.Items.Add($User.SamAccountName); } $ComboBox.Location = New-Object System.Drawing.Point(60,10) $main_form.Controls.Add($ComboBox)
Add two more labels to the form. The first should display a static label and the second one should display the last time the password for the selected AD user account was changed:
$Label2 = New-Object System.Windows.Forms.Label $Label2.Text = "Last Password Set:" $Label2.Location = New-Object System.Drawing.Point(0,40) $Label2.AutoSize = $true $main_form.Controls.Add($Label2) $Label3 = New-Object System.Windows.Forms.Label $Label3.Text = "" $Label3.Location = New-Object System.Drawing.Point(110,40) $Label3.AutoSize = $true $main_form.Controls.Add($Label3)
Now place the button on the form:
$Button = New-Object System.Windows.Forms.Button $Button.Location = New-Object System.Drawing.Size(400,10) $Button.Size = New-Object System.Drawing.Size(120,23) $Button.Text = "Check" $main_form.Controls.Add($Button)
Now assign an action to the button. After the button is clicked, the script should retrieve the value of the pwdLastSet attribute from Active Directory for the user selected in the $ComboBox:
$Button.Add_Click( { $Label3.Text = [datetime]::FromFileTime((Get-ADUser -identity $ComboBox.selectedItem -Properties pwdLastSet).pwdLastSet).ToString('MM dd yy : hh ss') } )
Use the Visible property to hide some of the GUI elements on a Windows form.
$Label3.Text.Visible = $false # or $True if you want to show it
Run the PowerShell script. As you can see, the drop-down list is automatically filled with the names of the user account names from Active Directory. When you select the user account and click the Check button, the form displays the time when the user’s password was last changed in Active Directory.
So, you have built your first simple graphical user interface for a PowerShell script. What’s next? Now you are ready to add more complex UI elements to your PowerShell form.
Commonly Used PowerShell UI Elements
Similarly, you can create the following graphic graphical on the form:
- CheckBox — used to list and select some options;
- RadioButton — lists some items and allows you to select only one;
- TextBox — text dialogue element for user input;
- Label — used to show text on a screen form;
- ChekedListBox — shows a list of items with checkboxes (allows to select multiple items);
- DataGridView — allows displaying some tabular data;
- GroupBox — allows a set of controls to be viewed and grouped together;
- ListBox — contains several text elements and allows you to select one or more items;
- TabControl — allows you to split your form into different areas (tabs);
- ListView — displays a list of items with text and (optionally) an icon;
- TreeView — hierarchical objects view;
- DateTimePicker — allows to select date and time value;
- TrackBar — scrollable control;
- PictureBox — allows to show a picture on the form;
- ProgressBar — indicates the operation progress;
- HScrollBar — horizontal scroll bar;
- VScrollBar — vertical scroll bar;
- ContextMenu — right-click menus;
- Menu — top menu in your form.
Building Interactive Graphical Menus for PowerShell Script
Use WinForms class to add complex hierarchical menus to your graphical PowerShell scripts. In this example, we will add some menu items to a previously created PowerShell form with a simple structure:
- File
- Open
- Save
- Exit
- Help
- About
To create a horizontal menu on a Windows form, you need to create a MenuStrip object. Use ToolStripMenuItem objects for menu items. ToolStripButton objects are used to bind actions (PowerShell functions) to menu items.
Create some new WinForms objects for your menu:
$menuMain = New-Object System.Windows.Forms.MenuStrip $mainToolStrip = New-Object System.Windows.Forms.ToolStrip $menuFile = New-Object System.Windows.Forms.ToolStripMenuItem $menuOpen = New-Object System.Windows.Forms.ToolStripMenuItem $menuSave = New-Object System.Windows.Forms.ToolStripMenuItem $menuExit = New-Object System.Windows.Forms.ToolStripMenuItem $menuHelp = New-Object System.Windows.Forms.ToolStripMenuItem $menuAbout = New-Object System.Windows.Forms.ToolStripMenuItem $toolStripOpen = New-Object System.Windows.Forms.ToolStripButton $toolStripSave = New-Object System.Windows.Forms.ToolStripButton $toolStripExit = New-Object System.Windows.Forms.ToolStripButton $toolStripAbout = New-Object System.Windows.Forms.ToolStripButton
Now you need to bind your menu to the GUI form ($main_form):
$main_form.MainMenuStrip = $menuMain $main_form.Controls.Add($menuMain) [void]$mainForm.Controls.Add($mainToolStrip)
Now you can display the first menu:
# Show Menu Bar [void]$main_Form.Controls.Add($menuMain) # Menu: File $menuFile.Text = "File" [void]$menuMain.Items.Add($menuFile)
Then add a dropdown items to the File menu:
# Menu: File -> Open $menuOpen.Text = "Open" $menuOpen.Add_Click({OpenFile}) [void]$menuFile.DropDownItems.Add($menuOpen) # Menu: File -> Save $menuSave.Text = "Save" $menuSave.Add_Click({SaveFile}) [void]$menuFile.DropDownItems.Add($menuSave) # Menu: File -> Exit
With the Add_Click method, you can add a click action to a menu item (in this example, clicking the menu will call a method to close the form and stop the PowerShell script):
$menuExit.Text = "Exit" $menuExit.Add_Click({$main_Form.Close()}) [void]$menuFile.DropDownItems.Add($menuExit)
Now you can add the next menu section:
# Menu: Help $menuHelp.Text = "Help" [void]$menuMain.Items.Add($menuHelp) # Menu: Help -> About $menuAbout.Text = "About" $menuAbout.Add_Click({ShowAbout}) [void]$menuHelp.DropDownItems.Add($menuAbout)
Run the PowerShell script. As you can see, a horizontal menu with nested submenu items has appeared at the top of the form.
In the code for some menu items, we have added handlers for the Click event on the menu item: SaveFile, OpenFile, ShowAbout. Now you need to define the functions that will be called when the menu items are clicked.
For example, add a PowerShell function ShowAbout:
function ShowAbout { [void] [System.Windows.MessageBox]::Show( "My simple PowerShell GUI script with dialog elements and menus v1.0", "About script", "OK", "Information" ) }
Hint. For the convenience of your users, you can convert your text PowerShell scripts into full-featured EXE apps. You can use the PS2EXE module to convert the PS1 script to EXE.
- Install the module from the PowerShell Gallery:
Install-Module ps2exe -Repository PSGallery
- Convert your PS1 script file into an EXE file:
ps2exe -inputFile "C:\PS\posh_gui.ps1" -outputFile "C:\PS\posh_gui.exe"
Using Standard Windows Dialog Components in PowerShell Scripts
You can use some of the standard Windows graphical dialogues to inform the user and prompt them to make a choice. Let’s take a look at some of the standard graphics window calls in PowerShell.
You can display a simple modal window with text and buttons using the System.Windows.MessageBox class. Use MessageBox to notify the user when something is done or to get an answer to a simple question.
The message is a mandatory MessageBox attribute. The title, button, and icon are optional.
For example, to show only an OK message box:
[void] [System.Windows.MessageBox]::Show( "All changes have been implemented successfully ", "Script completed", "OK", "Information" )
Display a message box that requires a response (YesNoCancel):
$answer = [System.Windows.MessageBox]::Show( "Dou you want to remove this user?", " Removal Confirmation", "YesNoCancel", "Warning" )
Prompt a user for credentials and split it on two variables:
$creds = Get-Credential $UserName $getUsername = $creds.GetNetworkCredential( ).UserName $getPassword = $creds.GetNetworkCredential( ).Password
Show the default Windows select file dialog box with a filter by file names:
Add-Type -AssemblyName System.Windows.Forms $initialDirectory = [Environment]::GetFolderPath('Desktop') $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog $OpenFileDialog.InitialDirectory = $initialDirectory $OpenFileDialog.Filter = 'Script files (*.ps1;*.cmd;*.bat)|*.ps1;*.bat;*.cmd' $OpenFileDialog.Multiselect = $false $response = $OpenFileDialog.ShowDialog( ) # $response can return OK or Cancel if ( $response -eq 'OK' ) { Write-Host 'You selected the file:' $OpenFileDialog.FileName }
Open the Browse for folder dialog box:
$shell = New-Object -ComObject Shell.Application $selectedfolder = $shell.BrowseForFolder( 0, 'Select a folder to proceed', 16, $shell.NameSpace( 17 ).Self.Path ).Self.Path
Select printer dialog form:
Add-Type -AssemblyName System.Windows.Forms $prntdlg = New-Object System.Windows.Forms.PrintDialog $prntdlg.AllowCurrentPage = $false $prntdlg.AllowPrintToFile = $trur $prntdlg.AllowSelection = $false $prntdlg.AllowSomePages = $true $prntdlg.ShowNetwork = $true $response = $prntdlg.ShowDialog( )# $response can return OK or Cancel if ( $response -eq 'OK' ) { Write-Host 'Selected printer:' $prntdlg.PrinterSettings.PrinterName }
Another useful PowerShell command for displaying graphical information from a script to a user is Out-GridView. You can use the Out-GridView cmdlet to display any data (PowerShell object attributes) in the form of a graphical grid, where you can filter and sort it by the criteria that you want.
For example, the following PowerShell service status check script lists the services that are running on Windows.
The user must select the desired services (several lines can be selected by holding down the Ctrl key) and save the selection to a variable.
$Svcs = Get-Service | Where-Object {$_.Status -EQ "Running"}| Out-GridView -Title "List of running services" -PassThru| Select -ExpandProperty Name
Now you can use the list of services selected by the user in the Out-GridView for further processing in your PowerShell script.
The -PassThru option is used to pass the selected objects in the table through the pipeline through the standard PowerShell pipe.
Hint. Other examples of using the Out-GridView cmdlet are described in the following articles:
Building PowerShell Scripts’ GUI Using Visual Studio
You can use Visual Studio with a WPF (Windows Presentation Foundation) as a simple PowerShell GUI builder. Download and install Visual Studio Community 2019 version.
WPF is a part of the .NET Framework that can be used to visualize user interfaces in Windows apps.
Run Microsoft Visual Studio and create a new Project (File > New > Project). Select Visual C# > Windows Forms App (.NET Framework)
Use the Windows Forms element in the left Toolbox pane to place your control element on the form (with drag&drop).
The Visual Studio will generate a XAML code for you. Save this code into the file C:\PS\Script\MainWindow.xaml. Open this file using Notepad and remove the following string:
x:Class="test.MainWindow”
And save the changes in the XAML file.
Now you can read this XAML code from your PowerShell script and display a Windows Form.
Use the following function to load the XAML object:
$XamlPath = “C:\PS\Script\MainWindow.xaml” [xml]$Global:xmlWPF = Get-Content -Path $XamlPath try{ Add-Type -AssemblyName PresentationCore,PresentationFramework,WindowsBase,system.windows.forms } catch { Throw "Failed to load WPF." } $Global:xamGUI = [Windows.Markup.XamlReader]::Load((new-object System.Xml.XmlNodeReader $xmlWPF)) $xmlWPF.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | %{ Set-Variable -Name ($_.Name) -Value $xamGUI.FindName($_.Name) -Scope Global }
To display your form use:
$xamGUI.ShowDialog()
There are also several commercial projects that make it easy to generate graphical template forms for PowerShell for your scripts (such as online PowerShell GUI Designer at https://poshgui.com/).
6 comments
I have the following script which a Sharepoint page from powershell. I want other users to access it outside the server by proving parameter as required. Is GUI Powershell the best way to do it?
——
$PageLayoutUrl = “/_catalogs/masterpage/BlankWebPartPage.aspx”
$PageName = “Pages/PageSix.aspx”
$pagecontent = [string]$_.PageContent
# Get site object and create publishing site object
$SPSite = Get-SPSite(“http://xx.xxx.xx.xx:6060”)
$PublishingSite = New-Object Microsoft.SharePoint.Publishing.PublishingSite($SPSite)
# Get web object and create publishing web object
$SPWeb = Get-SPWeb “http://xx.xx.xx.xx:6060”
$PublishingWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($SPWeb)
$LayoutsColl = $PublishingSite.GetPageLayouts($False)
# Get the page layout object and create Publishing Page based on it
$SPPageLayout = $LayoutsColl[$PageLayoutUrl]
$Page = $PublishingWeb.AddPublishingPage(“PageSix.aspx”, $SPPageLayout)
$Page.Title = “This is page six”
Write-Host “Creating $pagetitle”
$Page.ListItem[“Page Content”] = “PAGE SIX
TESTING 123 SENTENCE HERE. TESTING 123 SENTENCE HERE. TESTING 123 SENTENCE HERE.
adipiscing elit adipiscing elit adipiscing elit adipiscing elit adipiscing elit
Body page content enter here. Body page content enter here. Body page content enter here. Body page content enter here.
Body page content enter here. Body page content enter here.
Body page content enter here.”
$Page.Update();
$Page.CheckIn(“Page Created”)
$Page.ListItem.File.Publish(“Page Checked in and Publishing Completed”)
Good morning
Firstly can I just say thank you for this post as a complete beginner to this it has been immensely useful and allowed me to create all of my menus for the relatively simple tasks i was looking to do.
I have however tun into what seems in my mind to be a simple thing yet search after search has not revealed an answer for me. I have created a menu in Visual Studio that on the click of a button launches a second menu. The second menu contains a list of buttons that when clicked I want them to launch a pre-written power shell script. What I am failing to find is the command I need to add to teh On-Click function of the button that will launch a Powers hell script by clicking it ?
Excellent and very useful.
But i have a question:
Post adding the components and once form is ready.. can we convert to .exe? All i need is, double click an icon from my desktop and see my form?
Please advise!
Yes. you can use ps2exe. it is pretty simple to use and will work on most powershellscripts.
you can use iexpress, that’s implemented in Windows
I get a blank form and execution seems to be halted.
EDIT: Figured it out, I copy/pasted the show main form command, not cut/pasted!