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()