I mange to do form what is pinging servers.
Can someone help me to polish that script so it would look more professional way.
And I am not happy how I handle Dynamics Form Items LB_* and PB_*. (LB = Label, PB = PictureBox)
Also I was finally find away parallel pinging. But it is still not work nicely because it is under loop that why form handling is not so smooth.
You import csv file. Header: Name, Address. Separator is <Tab>
Sample csv file
Name Address google google.com powershell powershell.org
Code
function Set-LabelElement { Param( [Parameter(Mandatory=$true)][system.Windows.Forms.Label] $Label, [Parameter(Mandatory=$true)][string] $Text, [Parameter(Mandatory=$true)][int16] $Width, [Parameter(Mandatory=$true)][int16] $Height, [Parameter(Mandatory=$true)][int16] $LocationX, [Parameter(Mandatory=$true)][int16] $LocationY ) $Label.Name = ("LB_" + $text) $Label.text = $Text $Label.AutoSize = $false $Label.width = $Width $Label.height = $Height $Label.Anchor = "Top, Left" $Label.location = New-Object System.Drawing.Point($LocationX, $LocationY) $Label.Font = 'Microsoft Sans Serif,10' return $Label } function Set-PictureBoxElement { Param( [Parameter(Mandatory=$true)][system.Windows.Forms.PictureBox] $PictureBox, [Parameter(Mandatory=$true)][string] $Name, [Parameter(Mandatory=$true)][int16] $Width, [Parameter(Mandatory=$true)][int16] $Height, [Parameter(Mandatory=$true)][int16] $LocationX, [Parameter(Mandatory=$true)][int16] $LocationY ) $PictureBox.Name = ("PB_" + $Name) $PictureBox.width = $Width $PictureBox.height = $Height $PictureBox.Anchor = "Top, Left, Right" $PictureBox.location = New-Object System.Drawing.Point($LocationX, $LocationY) $PictureBox.BorderStyle = 1 return $PictureBox } function PreFormatPicture { Param( [Parameter(Mandatory=$true)][system.Windows.Forms.PictureBox] $PBox ) # Drawing Blue Backroud to "Status Bar" Begening of script $bmp = New-Object System.Drawing.Bitmap 1000, 20 $PenWidth = 20 $BluePen = new-object Drawing.Pen Blue $BluePen.width = $PenWidth $Graph1 = [Drawing.Graphics]::FromImage($bmp) $Graph1.DrawRectangle($BluePen, 10,0,990,20) $PBox.Image = $bmp return $PBox } function UpdateGraph { Param( [Parameter(Mandatory=$true)][system.Windows.Forms.PictureBox] $PBox, [Parameter(Mandatory=$true)][int16] $Value ) # Shifting picture to right and draw new status to left (over write existing) $bmp = New-Object System.Drawing.Bitmap $PBox.Image $TempGraph = [Drawing.Graphics]::FromImage($bmp) $PenWidth = 10 $RedPen = new-object Drawing.Pen Red $RedPen.width = $PenWidth $GreenPen = new-object Drawing.Pen Green $GreenPen.width = $PenWidth $TempGraph.DrawImage($bmp, 10, 0) if ($Value -eq 1){ $TempGraph.DrawRectangle($GreenPen, 5,0,1,20) } else { $TempGraph.DrawRectangle($RedPen, 5,0,1,20) } $PBox.Image = $bmp return $PBox } function Prepare { Param( [Parameter(Mandatory=$true)][System.Object[]] $PictureBoxs ) foreach ($PBox in $PictureBoxs) { Set-Variable -Name "$($PBox.Name)" -Value (PreFormatPicture -PBox (Get-Variable -Name "$($PBox.Name)" -ValueOnly -Scope Script)) -Scope Script } } function MainLoop { Param( [Parameter(Mandatory=$true)][object[]] $Servers ) $script:CancelLoop = $false do { foreach ($server in $servers) { while(@(get-job -state Running).count -ge 10){ start-sleep -Milliseconds 50 } Start-Job -Name $server -scriptblock $Pinging -ArgumentList $($server.Name), $($server.Address) | out-null } [System.Windows.Forms.Application]::DoEvents() $results = get-job | Wait-Job | Receive-Job | select-object ComputerName, ComputerAddress, Status [System.Windows.Forms.Application]::DoEvents() foreach ($server in $servers) { $Value = ($results | Where-Object {$_.ComputerName -eq $($server.Name) -and $_.ComputerAddress -eq $($server.Address)} | select-object Status).Status $TempName = ($Servers | Where-Object {$_.Name -eq $($server.Name) -and $_.Address -eq $($server.Address)} | Select-Object Name).Name Set-Variable -Name "PB_$TempName" -Value (UpdateGraph -Value $Value -PBox (Get-Variable -Name "PB_$TempName" -ValueOnly -Scope Script)) -Scope Script } start-sleep 0.1 [System.Windows.Forms.Application]::DoEvents() start-sleep 0.1 } until ($script:CancelLoop -eq $True) } function LoadData{ $Filter = "Text File (*.txt) | *.txt" $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{ InitialDirectory = "C:\UserData\Work\Powershell Scripts\atoll\" Filter = $Filter } $result = $FileBrowser.ShowDialog() if ($result -eq "OK") { $FileBrowser.FileNames $servers = Import-Csv -Path $($FileBrowser.FileNames) -Delimiter "`t" $servers = $servers | Where-Object {$_.Name -ne "" -or $_.Address -ne ""} } else { $servers = @() } return $servers } ########################################################################### $Pinging = { Param( [Parameter(Mandatory=$true)][string] $computerName, [Parameter(Mandatory=$true)][string] $computerAddress ) $ping = New-Object System.Net.NetworkInformation.Ping; try { [System.Net.NetworkInformation.PingReply]$res = $ping.Send($computerAddress) } catch [System.Net.NetworkInformation.PingException] { Write-Error $_ } $result = $res | select-object Status if ($result.Status -eq "Success") { new-object psobject -Property @{ ComputerName=$computerName; ComputerAddress=$computerAddress; Status=1; } } else { new-object psobject -Property @{ ComputerName=$computerName; ComputerAddress=$computerAddress; Status=0; } } } ########################################################################### add-Type -AssemblyName System.Windows.Forms [System.Windows.Forms.Application]::EnableVisualStyles() [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") $Width =1100 $Height = 35 $Size = $Width.ToString() + "," + $Height.ToString() $ItemWidth = 85 $ItemHeight = 25 $StatusHeight = 20 $Border = 5 $ItemCount = -1 $PB_Width = $Width - ($Border*3 + $ItemWidth *1) $Items = @() $Form = New-Object system.Windows.Forms.Form $Form.Name = "PingingTool" $Form.text = "Pinging Tool" $Form.TopMost = $false $Form.MinimizeBox = $false $Form.MaximizeBox = $false $Form.ClientSize = $Size $form.MinimumSize = New-Object System.Drawing.Size(($Width + 16),($Height + 39)) $form.MaximumSize = New-Object System.Drawing.Size(($Width + 16),($Height + 39)) $BT_Info = New-Object system.Windows.Forms.Button $BT_Info.text = "Info" $BT_Info.Name = "BT_Info" $BT_Info.width = $ItemWidth $BT_Info.height = $StatusHeight $BT_Info.Anchor = "Bottom, Right" $BT_Info.location = New-Object System.Drawing.Point($Border, ($Border + $ItemHeight * ($ItemCount + 1))) $BT_Info.Font = 'Microsoft Sans Serif,10' $BT_Load = New-Object system.Windows.Forms.Button $BT_Load.text = "Load" $BT_Load.Name = "BT_Load" $BT_Load.width = $ItemWidth $BT_Load.height = $StatusHeight $BT_Load.Anchor = "Bottom, Right" $BT_Load.location = New-Object System.Drawing.Point(($Width - ($Border+ $ItemWidth * 3)), ($Border + $ItemHeight * ($ItemCount + 1))) $BT_Load.Font = 'Microsoft Sans Serif,10' $BT_StartStop = New-Object system.Windows.Forms.Button $BT_StartStop.text = "Start" $BT_StartStop.Name = "BT_StartStop" $BT_StartStop.width = $ItemWidth $BT_StartStop.height = $StatusHeight $BT_StartStop.Anchor = "Bottom, Right" $BT_StartStop.location = New-Object System.Drawing.Point(($Width - ($Border+ $ItemWidth * 2)), ($Border + $ItemHeight * ($ItemCount + 1))) $BT_StartStop.Font = 'Microsoft Sans Serif,10' $BT_Exit = New-Object system.Windows.Forms.Button $BT_Exit.text = "Exit" $BT_Exit.Name = "BT_Exit" $BT_Exit.width = $ItemWidth $BT_Exit.height = $StatusHeight $BT_Exit.Anchor = "Bottom, Right" $BT_Exit.location = New-Object System.Drawing.Point(($Width - ($Border+ $ItemWidth * 1)), ($Border + $ItemHeight * ($ItemCount + 1))) $BT_Exit.Font = 'Microsoft Sans Serif,10' $BaseButtons = @($BT_Info, $BT_Load, $BT_Exit, $BT_StartStop) $Form.controls.AddRange($BaseButtons) $BT_StartStop.Add_Click({ if ($script:ItemCount -gt 0 ) { if ($BT_StartStop.Text -eq "Start") { Prepare -PictureBoxs ($Form.controls | Where-Object {$_.Name -like 'PB_*'}) $BT_StartStop.Text = "Stop" foreach ($Button in $BaseButtons) { if ($Button.Name -ne 'BT_StartStop') { $Button.enabled = $false } } [System.Windows.Forms.Application]::DoEvents() MainLoop -Servers $script:servers } else { $BT_StartStop.Text = "Start" $script:CancelLoop = $true foreach ($Button in $BaseButtons) { if ($Button.Name -ne 'BT_StartStop') { $Button.enabled = $true } } } } }) $BT_Load.Add_Click({ [array]$script:servers = LoadData $script:servers = $script:servers | Where-Object {($_.Name).Length -gt 0 -and ($_.Address).Length -gt 0} if($script:servers.Length -eq 0){ $script:ItemCount = -1 $List = $Form.controls | Where-Object {$_.Name -like "LB_*" -or $_.Name -like "PB_*" } foreach ($item in $List) { $form.controls.remove($item) Remove-Variable -Name $($item.Name) -Scope Script } $Height = (30 + $Border + $ItemHeight * ($ItemCount + 1)) $Size = $Width.ToString() + "," + $Height.ToString() $Form.ClientSize = $Size $form.MinimumSize = New-Object System.Drawing.Size(($Width + 16),($Height + 39)) $form.MaximumSize = New-Object System.Drawing.Size(($Width + 16),($Height + 39)) } else { $script:ItemCount = $script:servers.Length $List = $Form.controls | Where-Object {$_.Name -like "LB_*" -or $_.Name -like "PB_*" } foreach ($item in $List) { $form.controls.remove($item) Remove-Variable -Name $($item.Name) -Scope Script } if ($script:ItemCount -gt 0) { $Height = (30 + $Border + $ItemHeight * ($ItemCount + 1)) $Size = $Width.ToString() + "," + $Height.ToString() $Form.ClientSize = $Size $form.MinimumSize = New-Object System.Drawing.Size(($Width + 16),($Height + 39)) $form.MaximumSize = New-Object System.Drawing.Size(($Width + 16),($Height + 39)) $Items = @() $i = 0 foreach ($server in $servers) { $TempName = $server.Name New-Variable -Name "LB_$tempName" -Value (New-Object system.Windows.Forms.Label) -Scope Script Set-Variable -Name "LB_$tempName" -Value (Set-LabelElement -Label (Get-Variable -Name "LB_$tempName" -ValueOnly -Scope Script) -Text $TempName -Width $ItemWidth -Height $ItemHeight -LocationX $Border -LocationY ($Border + $ItemHeight * $i)) -Scope Script $Items = $Items + (Get-Variable -Name "LB_$tempName" -ValueOnly -Scope Script) New-Variable -Name "PB_$tempName" -Value (New-Object system.Windows.Forms.PictureBox) -Scope Script Set-Variable -Name "PB_$tempName" -Value (Set-PictureBoxElement -PictureBox (Get-Variable -Name "PB_$tempName" -ValueOnly -Scope Script) -Name "$tempName" -Width $PB_Width -Height $StatusHeight -LocationX ($ItemWidth + $Border) -LocationY ($Border + $ItemHeight * $i)) -Scope Script $Items = $Items + (Get-Variable -Name "PB_$tempName" -ValueOnly -Scope Script) $i = $i + 1 } $Form.controls.AddRange($Items) Prepare -PictureBoxs ($Form.controls | Where-Object {$_.Name -like 'PB_*'}) } } }) $BT_Exit.Add_Click({ # Exiting Script $Form.Close() }) $BT_Info.Add_Click({ # Info What kind CSV file need to be to import to tool. $Message = @(" Import CSV file: `r`n", "Headers: Name, Address `r`n", "Separator: " ) [System.Windows.Forms.Messagebox]::Show($Message) }) [void]$Form.ShowDialog() $Form.Dispose()