Share via


GUI Application with PowerShell – Ping Tool

So using XAML we are going to create a powershell GUI, which makes the user life easier. Let's say if we are giving this script to a non technical person or like if we want to give them like a fancy tool which eases out the interaction and the outputs, we  can use this type of GUI.

Just to give a heads up on XAML who are not familiar with that. As per the explanation provided by Microsoft:

/en-us/dotnet/framework/wpf/advanced/xaml-overview-wpf

XAML is a declarative markup language. As applied to the .NET Framework programming model, XAML simplifies creating a UI for a .NET Framework application. We can create visible UI elements in the declarative XAML markup, and then separate the UI definition from the run-time logic by using code-behind files, joined to the markup through partial class definitions. XAML directly represents the instantiation of objects in a specific set of backing types defined in assemblies. This is unlike most other markup languages, which are typically an interpreted language without such a direct tie to a backing type system. XAML enables a workflow where separate parties can work on the UI and the logic of an application, using potentially different tools.

When represented as text, XAML files are XML files that generally have the .xaml extension. The files can be encoded by any XML encoding, but encoding as UTF-8 is typical.

Starting to design the GUI…

We don´t have to sit and design everything by ourselves. Its not like old days we have to sit and write our own code for everything even to place buttons on a position. Since PowerShell doesn't have an IDE in terms of designing, we can use Visual studio to do the trick, and the good thing, it generates code as per our design. We just drag and drop the buttons and the textbox, put fancy style and copy paste the code to our powershell code.

So using Visual Studio Express 2013, create a WPF application. We would need visual studio for this, once installed or if we have it already, launch the application and select New Project > WPF Application.

https://jhansiranivedachalam.files.wordpress.com/2017/09/wpf_application.jpg?w=730

Voila, now we have our GUI in place, we can see the XAML generated. Cool now on top of that we can add controls like in the below image and format it.

https://jhansiranivedachalam.files.wordpress.com/2017/09/wpf1_application.jpg?w=730

So now we have quite a lot of tags generated. So now we can copy paste this to our PowerShell, But before doing this we  need to export a .net class to powershell as well, So PowerShell could always script almost everything in .NET, but, prior to the recent CTP2 we could not script Windows Presentation Foundation (WPF) in PowerShell.

Windows Presentation Foundation (WPF) is a set of .NET libraries for making next-generation user interfaces. In order to script WPF classes, we have to start them in a Single Threaded Apartment (STA).  Luckily, starting in CTP2, we can run code in an STA a few ways in PowerShell.

Lets to do that. Open Powershell ISE

https://jhansiranivedachalam.files.wordpress.com/2017/09/capture.png?w=730

So I have created a simple ping information tool using WPF in PowerShell. Below is the same script and the output as mentioned in the screenshot.

It takes a list of machines as input from the text box and displays their status in an output grid.

 

*************************************************************************************

###Ping Info####

*************************************************************************************

[void][System.Reflection.Assembly]::LoadWithPartialName(‘presentationframework’)

[xml]$XAML = @’
<Window
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation&#8221;
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml&#8221;
Title=”Information Tool” Height=”710.5″ Width=”1281.048″>

<Grid>
<Button Name=”button01″ Content=”Ping” HorizontalAlignment=”Left” Margin=”54,316,0,0″ VerticalAlignment=”Top” Width=”75″/>
<Label Name=”lbllabel” Content=”Server Names” HorizontalAlignment=”Left” Margin=”33,64,0,0″ VerticalAlignment=”Top” Height=”29″ Width=”88″/>
<TextBox Name=”txtserver” AcceptsReturn=”True” HorizontalAlignment=”Left” Height=”123″ Margin=”38,93,0,0″ TextWrapping=”Wrap” VerticalAlignment=”Top” Width=”236″ VerticalScrollBarVisibility=”Visible”/>
<Label Name=”lblhead” Content=”Ping Information Tool” HorizontalAlignment=”Left” Margin=”364,10,0,0″ VerticalAlignment=”Top” Height=”42″ Width=”249″ FontFamily=”Cambria” FontSize=”24″ FontWeight=”Bold”/>
<Button Name=”btnclient” Content=”SCCM Client” HorizontalAlignment=”Left” Margin=”302,316,0,0″ VerticalAlignment=”Top” Width=”92″/>
<Button Name=”btnpatch” Content=”Patch Count” HorizontalAlignment=”Left” Margin=”438,316,0,0″ VerticalAlignment=”Top” Width=”106″/>
<Button Name=”btnlastscan” Content=”Last Scan” HorizontalAlignment=”Left” Margin=”168,316,0,0″ VerticalAlignment=”Top” Width=”88″/>
<Button Name=”btnuptime” Content=”Uptime” HorizontalAlignment=”Left” Margin=”590,315,0,0″ VerticalAlignment=”Top” Width=”106″/>
<Button Name=”btnbios” Content=”NetBIOS Name” HorizontalAlignment=”Left” Margin=”726,316,0,0″ VerticalAlignment=”Top” Width=”106″/>
<Button Name=”btnapp” Content=”Package Installed” HorizontalAlignment=”Left” Margin=”856,316,0,0″ VerticalAlignment=”Top” Width=”116″/> 
</Grid>

</Window>
‘@

$reader=(New-Object System.Xml.XmlNodeReader $xaml) 
try{$Form=[Windows.Markup.XamlReader]::Load( $reader )}
catch{Write-Host “Unable to load Windows.Markup.XamlReader.”; exit}

$xaml.SelectNodes(“//*[@Name]”) | %{Set-Variable -Name ($_.Name) -Value $Form.FindName($_.Name)}
$fdate=Get-Date -Format o | foreach {$_ -replace “:”, “.”}

$fpath = “c:\Windows\Temp\Failed”+ $fdate +”.txt”
$spath = “c:\Windows\Temp\Sucess”+ $fdate +”.txt”
$ServerNamePath= “c:\Windows\Temp\ServerName”+$fdate +”.txt”
$BiosPath= “c:\Windows\Temp\Bios”+$fdate +”.txt”

$button01.add_Click({

$strname=$txtserver.Text 
$strname| Out-File $ServerNamePath

$sname = get-content $ServerNamePath

$sname = get-content $ServerNamePath | foreach {
Write-Verbose “Testing $_”
$test = Test-Connection -ComputerName $_ -Count 1 -ErrorAction SilentlyContinue
if($test) { 
$status = ‘OK’
$address = $test.IPV4Address
} else { 
$status = ‘Failed’
$address = ”
}
[PSCustomObject]@{
ServerName = $_
IPAddress = $address
‘Ping Status’ = $status
}
}

$sname | Out-GridView -Title “Ping Status”

})

$Form.ShowDialog() | out-null

*************************************************************************************

Output:

https://jhansiranivedachalam.files.wordpress.com/2017/09/capture1.png?w=730

https://jhansiranivedachalam.files.wordpress.com/2017/09/output.png?w=730