Powershell Host Availability Monitoring

Good day, I want to share a simple instruction "How can I stop manually pinging a dozen hosts. Without registration and SMS! ”







From the Internet



Important : I am not a programmer or a system administrator, but I have to work simultaneously with a large set of servers and services, and I wrote this script for my own convenience.



To all who may find this useful, curious, I ask under cat.




Why Powershell
I have experience writing simple Python programs, but it requires either an installed interpreter or the right to run .exe, which, as part of my work, is not always possible. But the Powershell script often finds the ability to run.



Not everyone loves the console / terminal



I think this is not a contradiction, otherwise everyone would still use console mail clients and a GUI would not appear in * nix-systems.



Since in everyday life I have to use Powershell rather primitively, for a start I tried to understand whether it is possible to fasten the GUI to it. It turns out you can, and even quite simple:









Add-Type -assembly System.Windows.Forms #  $main_form = New-Object System.Windows.Forms.Form #    "" #    $main_form.Text ='Links up' #   $main_form.Width = 300 #  $main_form.Height = 200 #  $main_form.AutoSize = $true #     ,   $main_form.ShowDialog() # ""
      
      





Add an output element to this and get an elementary Windwows tautology window ? .









 Add-Type -assembly System.Windows.Forms #  $main_form = New-Object System.Windows.Forms.Form #    "" #      $main_form.Text ='Links up' #   $main_form.Width = 300 #  $main_form.Height = 200 #  $main_form.AutoSize = $true #     ,   $Label = New-Object System.Windows.Forms.Label #      ,     ,      Powershell $Label.Text = "!   Windows-,    ?" #  $Label.Location = New-Object System.Drawing.Point(10,65) #        (x,y) $Label.AutoSize = $true $main_form.Controls.Add($Label) #    ,        $main_form.ShowDialog() #   
      
      





Add speakers



So the tool with which I “pinged Yandex” and mounted * .iso got a separate GUI, but this is not enough. Similarly, you can display information about accessibility, but for monitoring you will have to restart the script each time.



First, draw two icons and add the ability to display images.









 $PictureBox = New-Object system.Windows.Forms.PictureBox #       $PictureBox.width = 10 $PictureBox.height = 10 $PictureBox.location = New-Object System.Drawing.Point(178,12) #                #<b>test-connection</b>, : #-Count -  -  #-computer - IP      #-quiet -       Boolean  if ((test-connection -Count 1 -computer ya.ru -quiet) -eq $True) { $PictureBox.imageLocation = "C:\Test\yes.png" #     } Else { $PictureBox.imageLocation = "C:\Test\no.png" #     } $PictureBox.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::zoom $main_form.Controls.Add($PictureBox)
      
      





Again our DNS nicknames are naughty ...









And add a button so that you can update the readings.









 $Button = New-Object System.Windows.Forms.Button $Button.Location = New-Object System.Drawing.Size(100,150) $Button.Size = New-Object System.Drawing.Size(80,30) $Button.Text = "Reload" #        PictureBox     $Button.Add_Click({ if ((Test-Connection -Count 1 -computer ya.ru -quiet) -eq $True) {$PictureBox.imageLocation = "C:\Test\yes.png"} Else {$PictureBox.imageLocation = "C:\Test\no.png"} if ((Test-Connection -Count 1 -computer 8.8.8.8 -quiet) -eq $True) {$PictureBox1.imageLocation = "C:\Test\yes.png"} Else {$PictureBox1.imageLocation = "C:\Test\no.png"} }) $main_form.Controls.Add($Button)
      
      











Great, now in production! ?



Having manually prescribed about half a dozen hosts, I suddenly realized one thing - but this project will end, the hosts will change and I will have to edit the script every time. On the one hand, it’s okay, it’s the same decision for yourself. On the other hand, this is a decision for yourself beloved, you look at what happens:



The spectacle is not for the faint of heart
 Add-Type -assembly System.Windows.Forms #  $main_form = New-Object System.Windows.Forms.Form #    "" #      $main_form.Text ='Links up' #   $main_form.Width = 300 #  $main_form.Height = 200 #  $main_form.AutoSize = $true #     ,   $Label = New-Object System.Windows.Forms.Label #      ,     ,      Powershell $Label.Text = "ya.ru ............................" #  $Label.Location = New-Object System.Drawing.Point(15,10) #        (x,y) $Label.AutoSize = $true $Label1 = New-Object System.Windows.Forms.Label #      ,     ,      Powershell $Label1.Text = "8.8.8.8 ............................" #  googl- DNS- $Label1.Location = New-Object System.Drawing.Point(15,30) #        (x,y) $Label1.AutoSize = $true $Label2 = New-Object System.Windows.Forms.Label $Label2.Text = "192.168.xx ............................" $Label2.Location = New-Object System.Drawing.Point(15,50) $Label2.AutoSize = $true $Label3 = New-Object System.Windows.Forms.Label $Label3.Text = "192.168.xx ............................" $Label3.Location = New-Object System.Drawing.Point(15,70) $Label3.AutoSize = $true $Label4 = New-Object System.Windows.Forms.Label $Label4.Text = "10.0.xx ............................" $Label4.Location = New-Object System.Drawing.Point(15,90) $Label4.AutoSize = $true $Label5 = New-Object System.Windows.Forms.Label $Label5.Text = "162.102.xx ............................" $Label5.Location = New-Object System.Drawing.Point(15,110) $Label5.AutoSize = $true $PictureBox = New-Object system.Windows.Forms.PictureBox #       $PictureBox.width = 10 $PictureBox.height = 10 #                #<b>test-connection</b>, : #-Count -  -  #-computer - IP      #-quiet -       Boolean  $PictureBox.location = New-Object System.Drawing.Point(235,12) if ((test-connection -Count 1 -computer ya.ru -quiet) -eq $True) { $PictureBox.imageLocation = "C:\Test\yes.png" #     } Else { $PictureBox.imageLocation = "C:\Test\no.png" #     } $PictureBox.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::zoom $PictureBox1 = New-Object system.Windows.Forms.PictureBox #       $PictureBox1.width = 10 $PictureBox1.height = 10 $PictureBox1.location = New-Object System.Drawing.Point(235,32) if ((test-connection -Count 1 -computer 8.8.8.8 -quiet) -eq $True) { $PictureBox1.imageLocation = "C:\Test\yes.png" #     } Else { $PictureBox1.imageLocation = "C:\Test\no.png" #     } $PictureBox1.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::zoom $PictureBox2 = New-Object system.Windows.Forms.PictureBox #       $PictureBox2.width = 10 $PictureBox2.height = 10 $PictureBox2.location = New-Object System.Drawing.Point(235,52) if ((test-connection -Count 1 -computer 192.168.xx -quiet) -eq $True) { $PictureBox2.imageLocation = "C:\Test\yes.png" #     } Else { $PictureBox2.imageLocation = "C:\Test\no.png" #     } $PictureBox2.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::zoom $PictureBox3 = New-Object system.Windows.Forms.PictureBox #       $PictureBox3.width = 10 $PictureBox3.height = 10 $PictureBox3.location = New-Object System.Drawing.Point(235,72) if ((test-connection -Count 1 -computer 192.168.xx -quiet) -eq $True) { $PictureBox3.imageLocation = "C:\Test\yes.png" #     } Else { $PictureBox3.imageLocation = "C:\Test\no.png" #     } $PictureBox3.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::zoom $PictureBox4 = New-Object system.Windows.Forms.PictureBox #       $PictureBox4.width = 10 $PictureBox4.height = 10 $PictureBox4.location = New-Object System.Drawing.Point(235,92) if ((test-connection -Count 1 -computer 10.0.xx -quiet) -eq $True) { $PictureBox4.imageLocation = "C:\Test\yes.png" #     } Else { $PictureBox4.imageLocation = "C:\Test\no.png" #     } $PictureBox1.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::zoom $PictureBox5 = New-Object system.Windows.Forms.PictureBox #       $PictureBox5.width = 10 $PictureBox5.height = 10 $PictureBox5.location = New-Object System.Drawing.Point(235,112) if ((test-connection -Count 1 -computer 162.102.xx -quiet) -eq $True) { $PictureBox5.imageLocation = "C:\Test\yes.png" #     } Else { $PictureBox5.imageLocation = "C:\Test\no.png" #     } $PictureBox5.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::zoom $Button = New-Object System.Windows.Forms.Button $Button.Location = New-Object System.Drawing.Size(100,150) $Button.Size = New-Object System.Drawing.Size(80,30) $Button.Text = "Reload" #        PictureBox     $Button.Add_Click({ if ((Test-Connection -Count 1 -computer ya.ru -quiet) -eq $True) {$PictureBox.imageLocation = "C:\Test\yes.png"} Else {$PictureBox.imageLocation = "C:\Test\no.png"} if ((Test-Connection -Count 1 -computer 8.8.8.8 -quiet) -eq $True) {$PictureBox1.imageLocation = "C:\Test\yes.png"} Else {$PictureBox1.imageLocation = "C:\Test\no.png"} if ((Test-Connection -Count 1 -computer 192.168.xx -quiet) -eq $True) {$PictureBox2.imageLocation = "C:\Test\yes.png"} Else {$PictureBox2.imageLocation = "C:\Test\no.png"} if ((Test-Connection -Count 1 -computer 192.168.xx -quiet) -eq $True) {$PictureBox3.imageLocation = "C:\Test\yes.png"} Else {$PictureBox3.imageLocation = "C:\Test\no.png"} if ((Test-Connection -Count 1 -computer 10.0.xx -quiet) -eq $True) {$PictureBox4.imageLocation = "C:\Test\yes.png"} Else {$PictureBox4.imageLocation = "C:\Test\no.png"} if ((Test-Connection -Count 1 -computer 162.102.xx -quiet) -eq $True) {$PictureBox5.imageLocation = "C:\Test\yes.png"} Else {$PictureBox5.imageLocation = "C:\Test\no.png"} }) $main_form.Controls.Add($Label) #    ,        $main_form.Controls.Add($Label1) $main_form.Controls.Add($Label2) $main_form.Controls.Add($Label3) $main_form.Controls.Add($Label4) $main_form.Controls.Add($Label5) $main_form.Controls.Add($PictureBox) $main_form.Controls.Add($PictureBox1) $main_form.Controls.Add($PictureBox2) $main_form.Controls.Add($PictureBox3) $main_form.Controls.Add($PictureBox4) $main_form.Controls.Add($PictureBox5) $main_form.Controls.Add($Button) $main_form.ShowDialog() #   
      
      





Even if you observe cleanliness and adhere to the structure, periodic editing will not cause the most pleasant sensations.



To begin with, we make the availability check in a separate function, and the directory path in a separate variable:



 $script_path = "C:\Test\PS ping" #      PictureBox  IP-   . #     . function get_status($PictureBox,$path_ip) { if ((Test-Connection -Count 1 -computer $path_ip -quiet) -eq $True) {$PictureBox.imageLocation = $script_path + "\yes.png"} Else {$PictureBox.imageLocation = $script_path + "\no.png"} }
      
      





We will transfer the host data to an external path.txt file, writing it in the form of “ip / host-functional-name /”, and in the document we will take them into arrays. We also make the calculation of the Y position more automated. All this gives us the opportunity to create Labels and checkboxes by calling the function:









 #  ,   :  Label, IP-,      Y Function Create_line($label,$path_ip,$caption, $top){ $label.Location = New-Object System.Drawing.Point(1, $top) $label.text = $path_ip+$caption $label.font = $font $Label.AutoSize = $true } #    ,   :  PictureBox, IP-     Y Function Create_link($PictureBox,$path_ip, $top){ $PictureBox.width = 10 $PictureBox.height = 10 $PictureBox.location = New-Object System.Drawing.Point(210,$top) get_status -PictureBox $PictureBox -path_ip $path_ip $PictureBox.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::zoom } $line = Get-content -LiteralPath $script_path"\path.txt" #     $len = $line.Length # ,       $i = 0 #      $ip = @() # ip $capt = @() #  $Labels =@() # Label $PictureBoxs =@() # PictureBox while($i -lt $len){ $f = $line[$i].IndexOf("/") #    $l = $line[$i].LastIndexOf("/") #    $ip += $line[$i].Substring(0,$f) # ip $capt += $line[$i].Substring($f+1,$l-$f-1) #  #  Label Create_line -label ($label_obj = New-Object System.Windows.Forms.Label) -path_ip $ip[$i] -caption $capt[$i] -top $label_from_top #  PictureBox Create_link -PictureBox ($PictureBox_obj = New-Object system.Windows.Forms.PictureBox) -path_ip $ip[$i] -top $label_from_top $label_from_top += 15 # ""   Y $Labels += $label_obj #  Label    $PictureBoxs += $PictureBox_obj #  PictureBox    $main_form.Controls.Add($Labels[$i]) $main_form.Controls.Add($PictureBoxs[$i]) $i +=1 }
      
      





We will add a place to display the time of the last check, because it is convenient, and we will slightly add an action when clicking the button.









 $Label0 = New-Object System.Windows.Forms.Label $Label0.Text = Get-Date $Label0.Location = New-Object System.Drawing.Point(80,180) $Label0.AutoSize = $true $main_form.Controls.Add($Label0) $Button.Add_Click({ while($i -lt $len){ get_status -PictureBox $PictureBoxs[$i] -path_ip $ip[$i] $i +=1 } $Label0.Text = Get-Date })
      
      





And also I attached a small feature not a bug , which upon detection of an inaccessible host reported not only a change in the indicator, but also screamed from the speakers.



 Add-Type -AssemblyName System.Speech $voice = New-Object System.Speech.Synthesis.SpeechSynthesizer $voice.Rate = 5 $voice.Speak("! !    !")
      
      





So after a few embellishments and bringing to a readable comfortable look for me , it turned out like this:



Full script code
 Add-Type -AssemblyName System.Speech Add-Type -assembly System.Windows.Forms $script_path = "C:\PS ping" $label_from_top = 10 $voice = New-Object System.Speech.Synthesis.SpeechSynthesizer $voice.Rate = 5 #      PictureBox  IP-   . #     . function get_status($PictureBox,$path_ip) { if ((Test-Connection -Count 1 -computer $path_ip -quiet) -eq $True) { $PictureBox.imageLocation = $script_path + "\yes.png" } Else { $PictureBox.imageLocation = $script_path + "\no.png" $voice.Speak("!  " + $path_ip + ", !") } } #  ,   :  Label, IP-,      Y Function Create_line($label,$path_ip,$caption, $top){ $label.Location = New-Object System.Drawing.Point(1, $top) $label.text = $path_ip+$caption $label.font = $font $Label.AutoSize = $true } #    ,   :  PictureBox, IP-     Y Function Create_link($PictureBox,$path_ip, $top){ $PictureBox.width = 10 $PictureBox.height = 10 $PictureBox.location = New-Object System.Drawing.Point(210,$top) get_status -PictureBox $PictureBox -path_ip $path_ip $PictureBox.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::zoom } $main_form = New-Object System.Windows.Forms.Form $main_form.Text ='Links up' #   $main_form.Width = 300 #  $main_form.Height = 200 #  $main_form.AutoSize = $true #     ,   $main_form.TopMost = $true #   ,        $line = Get-content -LiteralPath $script_path"\path.txt" #     $len = $line.Length # ,       $i = 0 #      $ip = @() # ip $capt = @() #  $Labels =@() # Label $PictureBoxs =@() # PictureBox while($i -lt $len){ $f = $line[$i].IndexOf("/") #    $l = $line[$i].LastIndexOf("/") #    $ip += $line[$i].Substring(0,$f) # ip $capt += $line[$i].Substring($f+1,$l-$f-1) #  #  Label Create_line -label ($label_obj = New-Object System.Windows.Forms.Label) -path_ip $ip[$i] -caption $capt[$i] -top $label_from_top #  PictureBox Create_link -PictureBox ($PictureBox_obj = New-Object system.Windows.Forms.PictureBox) -path_ip $ip[$i] -top $label_from_top $label_from_top += 15 # ""   Y $Labels += $label_obj #  Label    $PictureBoxs += $PictureBox_obj #  PictureBox    $main_form.Controls.Add($Labels[$i]) $main_form.Controls.Add($PictureBoxs[$i]) $i +=1 } #      $Label0 = New-Object System.Windows.Forms.Label $Label0.Text = Get-Date $Label0.Location = New-Object System.Drawing.Point(80,180) $Label0.AutoSize = $true #        PictureBox     $Button = New-Object System.Windows.Forms.Button $Button.Location = New-Object System.Drawing.Size(100,200) $Button.Size = New-Object System.Drawing.Size(80,30) $Button.Text = "Reload" $Button.Add_Click({ while($i -lt $len){ get_status -PictureBox $PictureBoxs[$i] -path_ip $ip[$i] $i +=1 } $i = 0 $Label0.Text = Get-Date }) $main_form.Controls.Add($Button) $main_form.Controls.Add($Label0) $main_form.ShowDialog()
      
      







Afterword



I hope someone will find this tutorial useful. If you did this almost from the cradle, then congratulations, I didn’t. But I am ready to listen to your comments and suggestions.



For me, it was nice to dig around and collect just such a small, but useful utility in everyday life. The plans still have to implement the addition and removal of nodes from the GUI, as well as to do the same thing that should have been implemented primarily automatic status updates without the need to "poke" the button and so that it does not hang "powershell.exe".



The latest version of the script on GitHub



All Articles