PowerShell – PING in GUI Window v1

email me

PING a computer and show active results in a GUI Window (not as easy as it sounds).

 

Get user input

 

Show results

 

Code

# MrNetTek
# eddiejackson.net/blog
# 5/8/2020
# free for public use 
# free to claim as your own

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

Function Get-UserInput {

    $form1 = New-Object System.Windows.Forms.Form
    $form1.Icon = 'C:\PowerShell\PowerShell.ico'
    $form1.Text = 'PING Computer'
    $form1.Size = New-Object System.Drawing.Size(300,200)
    $form1.StartPosition = 'CenterScreen'

    $okButton1 = New-Object System.Windows.Forms.Button
    $okButton1.Location = New-Object System.Drawing.Point(75,120)
    $okButton1.Size = New-Object System.Drawing.Size(75,23)
    $okButton1.Text = 'OK'
    $okButton1.DialogResult = [System.Windows.Forms.DialogResult]::OK
    $form1.AcceptButton = $okButton1
    $form1.Controls.Add($okButton1)

    $cancelButton1 = New-Object System.Windows.Forms.Button
    $cancelButton1.Location = New-Object System.Drawing.Point(150,120)
    $cancelButton1.Size = New-Object System.Drawing.Size(75,23)
    $cancelButton1.Text = 'Cancel'
    $cancelButton1.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
    $form1.CancelButton = $cancelButton1
    $form1.Controls.Add($cancelButton1)

    $label1 = New-Object System.Windows.Forms.Label
    $label1.Location = New-Object System.Drawing.Point(10,20)
    $label1.Size = New-Object System.Drawing.Size(280,20)
    $label1.Text = 'Enter computer name to PING:'
    $form1.Controls.Add($label1)

    $textBox1 = New-Object System.Windows.Forms.TextBox
    $textBox1.Location = New-Object System.Drawing.Point(10,40)
    $textBox1.Size = New-Object System.Drawing.Size(260,20)
    $form1.Controls.Add($textBox1)

    $form1.Topmost = $true

    $form1.Add_Shown({$textBox1.Select()})
    $result = $form1.ShowDialog()

    if ($result -eq [System.Windows.Forms.DialogResult]::OK)
        {
            $x = $textBox1.Text	
		
        }
    else 
    {
        $ProcessID = [System.Diagnostics.Process]::GetCurrentProcess()
	    $ProcessID = $ProcessID.ID
	    & taskkill /PID $ProcessID /t /f
    }   

    if ($x -eq '')
	    {
            [System.Windows.Forms.MessageBox]::Show("Enter a computer name." , "PING")
            Get-UserInput
	    }
    else
    {
        return $x
    }
	
}

$UserInput = Get-UserInput

$Global:SyncTable = [HashTable]::Synchronized(@{})
$SyncTable.CompName = "$UserInput"
$SyncTable.ContinuePing = $true
$SyncTable.CloseScript = $false
$SyncTable.Grid_Ping_Array = New-Object System.Collections.ArrayList

$Runspace1 = [RunspaceFactory]::CreateRunspace()
$Runspace1.ApartmentState = "STA"
$Runspace1.ThreadOptions = "ReuseThread"
$Runspace1.Open()
$Runspace1.SessionStateProxy.SetVariable("SyncTable",$SyncTable)
$psScript = [Powershell]::Create().AddScript({
	$UserInput = $SyncTable.CompName
	Add-Type -AssemblyName PresentationFramework,PresentationCore,WindowsBase

Function End-Script {
	$ProcessID = [System.Diagnostics.Process]::GetCurrentProcess()
	$ProcessID = $ProcessID.ID
	& taskkill /PID $ProcessID /t /f
}

Function Btn_CancelClose_Click {
	$BtnContent = $SyncTable.Btn_CancelClose.Content
	if ($BtnContent -ne "Cancel") {
		$SyncTable.CloseScript = $true        
		End-Script
	}
	$SyncTable.ContinuePing = $false
}

Function Window_Activated {
	$SyncTable.Window.TopMost = $false
	$SyncTable.Window.ShowInTaskBar = $true
}

$form1Main_FormClosing=[System.Windows.Forms.FormClosingEventHandler]{

	if($form1Main.DialogResult -ne 'OK')
	{
		$_.Cancel = $true
	}	
}


	[XML]$xaml = @'
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="" Height="350" Width="425" ShowInTaskbar="False" Topmost="True" WindowStartupLocation="CenterScreen">
    <Grid>
        <Label x:Name="Lbl_CompName" Content="" VerticalAlignment="Top" HorizontalContentAlignment="Center" Margin="5,5"/>
        <DataGrid x:Name="Grid_Ping" Margin="5,35,5,130" IsReadOnly="True" AutoGenerateColumns="False" ItemBindingGroup="{Binding}" SelectionUnit="FullRow" HeadersVisibility="Column">
            <DataGrid.Columns>
                <DataGridTextColumn x:Name="Col_Reply" Binding="{Binding Path=ReplyIP}" Header="Reply From"/>
                <DataGridTextColumn x:Name="Col_Status" Binding="{Binding Path=Status}" Header="Status"/>
                <DataGridTextColumn x:Name="Col_Bytes" Binding="{Binding Path=Bytes}" Header="Bytes"/>
                <DataGridTextColumn x:Name="Col_Time" Binding="{Binding Path=Time}" Header="Time"/>
                <DataGridTextColumn x:Name="Col_TTL" Binding="{Binding Path=TTL}" Header="TTL"/>
            </DataGrid.Columns>
        </DataGrid>
        <Border BorderThickness="1" BorderBrush="Black" Height="90" VerticalAlignment="Bottom" Margin="5,5,5,30"/>
        <Label x:Name="Lbl_PingStats" Content="" VerticalAlignment="Bottom" Margin="5,5,5,30" Height="90"/>
        <Button x:Name="Btn_CancelClose" Content="Cancel" HorizontalAlignment="Right" VerticalAlignment="Bottom" Width="75" Margin="5,5,5,5"/>
    </Grid>
</Window>
'@

$XMLReader = (New-Object System.Xml.XmlNodeReader $xaml)
$SyncTable.Window = [Windows.Markup.XamlReader]::Load($XMLReader)
$SyncTable.Window.Add_Closed({End-Script})
$SyncTable.Window.Add_Activated({Window_Activated})
$SyncTable.Window.Title = "PING - $UserInput"
$SyncTable.Lbl_CompName = $SyncTable.Window.FindName("Lbl_CompName")
$SyncTable.Lbl_CompName.Content = "$UserInput"
$SyncTable.Grid_Ping = $SyncTable.Window.FindName("Grid_Ping")
$SyncTable.Lbl_PingStats = $SyncTable.Window.FindName("Lbl_PingStats")
$SyncTable.Lbl_PingStats.Content = ""
$SyncTable.Btn_CancelClose = $SyncTable.Window.FindName("Btn_CancelClose")
$SyncTable.Btn_CancelClose.Add_Click({Btn_CancelClose_Click})
$Timer = New-Object System.Windows.Threading.DispatcherTimer
$Timer.Interval = [TimeSpan]"0:0:0.50"
$Action = {
	$SyncTable.Grid_Ping.ItemsSource = $SyncTable.Grid_Ping_Array
	$SyncTable.Lbl_PingStats.Content = $Synctable.PingLabel
	$SyncTable.Grid_Ping.ScrollIntoView($SyncTable.Grid_Ping.Items[$SyncTable.Grid_Ping.Items.Count - 1])
	$SyncTable.Grid_Ping.UpdateLayout()
	if ($SyncTable.ContinuePing -ne $true) {
		$SyncTable.Btn_CancelClose.Content = "Close"
		$Timer.Stop()
	}
}
$Timer.Add_Tick($Action)
$Timer.Start()
$SyncTable.Window.ShowDialog() | Out-Null
})
$psScript.Runspace = $Runspace1
$Handle = $psScript.BeginInvoke()

$NumSuccess = 0
$NumUnsuccess = 0
$Count = 0
$IP = $null
$MinResTime = 0
$MaxResTime = 0
$AverageResTime = $null
$TotalResTime = 0

do {
	$ResponseTime = $null
	$ReplySize = $null
	$TTL = $null
	$StatusCode = $null
	$Count++
	$strQuery = "Select * from Win32_PingStatus where Address='$UserInput'" 
	$ping = Get-WmiObject -query $strQuery
	$IP = $ping.IPV4Address.IPAddressToString
	$ReplySize = $ping.ReplySize
	$ResponseTime = $ping.ResponseTime | Out-String
	$ResponseTimeText = "$ResponseTime ms"
	$ResponseTimeText = $ResponseTimeText.Replace("`n","").replace("`r","")
	$TTL = $ping.ResponseTimeToLive
	$StatusCode = $ping.StatusCode
	if ($StatusCode -eq 0) {
		$NumSuccess++
		
		$Results = Select-Object -InputObject "" ReplyIP, Status, Bytes, Time, TTL
		$Results.ReplyIP = $IP
		$Results.Status = "Successful"
		$Results.Bytes = $ReplySize
		$Results.Time = $ResponseTimeText
		$Results.TTL = $TTL
		$SyncTable.Grid_Ping_Array += $Results
		
		$PercentLoss = ($NumUnsuccess / $Count) * 100
		$PercentLoss = [Math]::Round($PercentLoss, 0)
		if ($ResponseTime -gt $MaxResTime -or $MaxResTime -eq $null) {$MaxResTime = $ResponseTime}
		if ($ResponseTime -lt $MinResTime -or $MinResTime -eq $null) {$MinResTime = $ResponseTime}
		$TotalResTime = $TotalResTime + $ResponseTime
		$AverageResTime = $TotalResTime / $NumSuccess
		$AverageResTimeRounded = [Math]::Round($AverageResTime, 2)
		$MinResTimeText = $MinResTime | Out-String
		$MinResTimeText = $MinResTimeText.replace("`n","").replace("`r","")
		$MaxResTimeText = $MaxResTime | Out-String
		$MaxResTimeText = $MaxResTimeText.replace("`n","").replace("`r","")
		$Synctable.PingLabel = "Ping statistics for $IP" + ":`nPackets: Sent = $count" + ", Successful = $NumSuccess" + ", Unsuccessful = $NumUnsuccess (" + $PercentLoss + "% loss),`nApproximate round trip in milli-seconds:`nMinimum = $MinResTimeText" + "ms, Maximum = $MaxResTimeText" + "ms, Average = $AverageResTimeRounded" + "ms"
	}
	else {
		$NumUnsuccess++
		$Results = Select-Object -InputObject "" ReplyIP, Status
		$Results.ReplyIP = $IP
		$Results.Status = "Unsuccessful"
		$SyncTable.Grid_Ping_Array += $Results
		$PingResults.Rows.Add($IP,"Unsuccessful")
		$PercentLoss = ($NumUnsuccess / $Count) * 100
		$PercentLoss = [Math]::Round($PercentLoss, 2)
		$TotalResTime = $TotalResTime + $ResponseTime
		$MinResTimeText = $MinResTime | Out-String
		$MinResTimeText = $MinResTimeText.replace("`n","").replace("`r","")
		$MaxResTimeText = $MaxResTime | Out-String
		$MaxResTimeText = $MaxResTimeText.replace("`n","").replace("`r","")
		$Synctable.PingLabel = "Ping statistics for $IP" + ":`nPackets: Sent = $count" + ", Successful = $NumSuccess" + ", Unsuccessful = $NumUnsuccess (" + $PercentLoss + "% loss),`nApproximate round trip in milli-seconds:`nMinimum = $MinResTimeText" + "ms, Maximum = $MaxResTimeText" + "ms, Average = $AverageResTime" + "ms"
	}
	Start-Sleep -Milliseconds 500
} while ($SyncTable.ContinuePing -eq $true)

do {
	Start-Sleep 10
} while ($SyncTable.CloseScript -ne $true)

 

Notes

Download the Powershell Icon