Monitoraggio della disponibilità degli host con Powershell

Buon pomeriggio a tutti, voglio condividere una semplice guida su "Come smettere di pingare manualmente un numero di host. Senza registrazione e SMS!".

Monitoraggio della disponibilità degli host con PowershellDai misteri di Internet

Importante: non sono un programmatore né un amministratore di sistema, ma devo lavorare contemporaneamente con un ampio insieme server di servizi e ho scritto questo script per la mia comodità.

A chiunque possa esserne interessato, vi invito a proseguire.

Perché PowershellHo esperienza nella scrittura di semplici programmi in Python, ma richiede un interprete installato o i diritti per eseguire .exe, il che, nel contesto del mio lavoro, non è sempre possibile. Tuttavia, uno script in Powershell trova più facilmente la possibilità di essere eseguito.

Non tutti amano la console/il terminale

Credo che non ci sia contraddizione, altrimenti tutti userebbero client di posta via console e non ci sarebbe stata l’introduzione di GUI nei sistemi *nix.

Poiché nella vita di tutti i giorni utilizzo Powershell in un modo piuttosto primitivo, all’inizio ho cercato di capire se fosse possibile aggiungere un'interfaccia GUI. A quanto pare, è possibile, e anche piuttosto semplice:

Monitoraggio della disponibilità degli host con Powershell

Add-Type -assembly System.Windows.Forms #Colleghiamo la libreria
$main_form = New-Object System.Windows.Forms.Form #Creiamo un oggetto con la nostra "finestra"

#Impostiamo i parametri
$main_form.Text ='Links up' #Nome nel titolo
$main_form.Width = 300 #Larghezza della finestra
$main_form.Height = 200 #Altezza della finestra
$main_form.AutoSize = $true #Consentiamo di ridimensionarsi autonomamente, se necessario
$main_form.ShowDialog() #Mostriamo la "finestra"

Aggiungiamo a questo elemento un output e otteniamo una finestra Windows elementare, tautologia?.

Monitoraggio della disponibilità degli host con Powershell

Add-Type -assembly System.Windows.Forms #Colleghiamo la libreria

$main_form = New-Object System.Windows.Forms.Form #Creiamo una variabile con la nostra "finestra"

#Impostiamo i parametri della finestra
$main_form.Text ='Links up' #Nome nella barra del titolo
$main_form.Width = 300 #Larghezza della finestra
$main_form.Height = 200 #Altezza della finestra
$main_form.AutoSize = $true #Consentiamo la ridimensionamento automatico quando necessario

$Label = New-Object System.Windows.Forms.Label #Tutti gli elementi della finestra saranno assegnati a variabili, ma in realtà sono oggetti, come qualsiasi altra variabile in Powershell
$Label.Text = "Ciao! Sono una finestra Windows elementare, e tu che cosa hai raggiunto?" #Testo visualizzato
$Label.Location  = New-Object System.Drawing.Point(10,65) #Posizione dell'oggetto all'interno della finestra in orizzontale e verticale (x,y)
$Label.AutoSize = $true 

$main_form.Controls.Add($Label) #Aggiungiamo l'oggetto creato alla finestra, affinché non si perda durante l'esecuzione dello script

$main_form.ShowDialog() #Chiamiamo l'elemento della finestra elementare

Aggiungiamo dinamicità

Quindi, lo strumento con cui ho "pingato Yandex" e montato *.iso ha acquisito un'interfaccia grafica dedicata, ma non basta. In questo modo è possibile visualizzare le informazioni sulla disponibilità, ma per il monitoraggio dovrò riavviare lo script ogni volta.

Per cominciare, disegniamo due icone e aggiungiamo la possibilità di visualizzare immagini.

Monitoraggio della disponibilità degli host con Powershell

$PictureBox = New-Object system.Windows.Forms.PictureBox #L'oggetto per la visualizzazione delle immagini ha un nome piuttosto logico
$PictureBox.width = 10
$PictureBox.height = 10
$PictureBox.location = New-Object System.Drawing.Point(178,12)

#Qui entriamo nel vivo collegando l'immagine da visualizzare al risultato del test di accessibilità del nodo utilizzando il cmdlet
#<b>test-connection</b>, dove:
#-Count - specifica il numero di richieste
#-computer - IP o nome di dominio per la richiesta
#-quiet - per ricevere solo un valore booleano
if ((test-connection -Count 1 -computer ya.ru -quiet) -eq $True) {
	$PictureBox.imageLocation = "C:Testyes.png" #L'oggetto si riferisce all'immagine corrispondente
}
Else {
	$PictureBox.imageLocation = "C:Testno.png" #L'oggetto si riferisce all'immagine corrispondente
}
$PictureBox.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::zoom

$main_form.Controls.Add($PictureBox)

I nostri DNS stanno di nuovo dando problemi…

Monitoraggio della disponibilità degli host con Powershell
Aggiungiamo anche un pulsante per avere la possibilità di aggiornare le letture.

Monitoraggio della disponibilità degli host con Powershell

$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 = "Ricarica"

# Colleghiamo l'evento di clic del pulsante all'ogni PictureBox secondo la logica precedentemente descritta
$Button.Add_Click({ 
	if ((Test-Connection -Count 1 -computer ya.ru -quiet) -eq $True)
		{$PictureBox.imageLocation	= "C:Testyes.png"}
	Else {$PictureBox.imageLocation	= "C:Testno.png"}
	  
	if ((Test-Connection -Count 1 -computer 8.8.8.8 -quiet) -eq $True)
		{$PictureBox1.imageLocation	= "C:Testyes.png"}
	Else {$PictureBox1.imageLocation	= "C:Testno.png"}
 	})

$main_form.Controls.Add($Button)

Monitoraggio della disponibilità degli host con Powershell

Meraviglioso, ora in produzione!?

Scrivendo manualmente circa una dozzina di host, ho improvvisamente capito una cosa: questo progetto finirà, gli host cambieranno e dovrò ogni volta modificare lo script. Da un lato niente di grave, è pur sempre una soluzione per me. Dall'altro lato, date un'occhiata a cosa sta uscendo:

Uno spettacolo non per i deboli di cuore.

Add-Type -assembly System.Windows.Forms #Colleghiamo la libreria

$main_form = New-Object System.Windows.Forms.Form #Creiamo una variabile per la nostra "finestra"

#Impostiamo i parametri per essa
$main_form.Text ='Links up' #Nome nel titolo
$main_form.Width = 300 #Larghezza della finestra
$main_form.Height = 200 #Altezza della finestra
$main_form.AutoSize = $true #Consenti di ridimensionarsi automaticamente, se necessario

$Label = New-Object System.Windows.Forms.Label #Tutti gli elementi del modulo saranno memorizzati in variabili, ma in realtà sono oggetti, come tutte le altre variabili in Powershell
$Label.Text = "ya.ru		............................" #Testo visualizzato 
$Label.Location  = New-Object System.Drawing.Point(15,10) #Posizione dell'oggetto all'interno del modulo orizzontalmente e verticalmente (x,y)
$Label.AutoSize = $true 

$Label1 = New-Object System.Windows.Forms.Label #Tutti gli elementi del modulo saranno memorizzati in variabili, ma in realtà sono oggetti, come tutte le altre variabili in Powershell
$Label1.Text = "8.8.8.8		............................" #Testo visualizzato DNS di Google
$Label1.Location  = New-Object System.Drawing.Point(15,30) #Posizione dell'oggetto all'interno del modulo orizzontalmente e verticalmente (x,y)
$Label1.AutoSize = $true 

$Label2 = New-Object System.Windows.Forms.Label
$Label2.Text = "192.168.x.x	............................"
$Label2.Location  = New-Object System.Drawing.Point(15,50)
$Label2.AutoSize = $true

$Label3 = New-Object System.Windows.Forms.Label
$Label3.Text = "192.168.x.x	............................"
$Label3.Location  = New-Object System.Drawing.Point(15,70)
$Label3.AutoSize = $true

$Label4 = New-Object System.Windows.Forms.Label
$Label4.Text = "10.0.x.x	 ............................"
$Label4.Location  = New-Object System.Drawing.Point(15,90)
$Label4.AutoSize = $true

$Label5 = New-Object System.Windows.Forms.Label
$Label5.Text = "162.102.x.x	 ............................"
$Label5.Location  = New-Object System.Drawing.Point(15,110)
$Label5.AutoSize = $true

$PictureBox = New-Object system.Windows.Forms.PictureBox #Oggetto per la visualizzazione delle immagini, logicamente chiamato
$PictureBox.width = 10
$PictureBox.height = 10

#Qui passiamo alla parte pratica collegando l'immagine visualizzata al risultato della verifica di accessibilità del nodo utilizzando il cmdlet
#<b>test-connection</b>, dove:
#-Count - passa il numero di richieste
#-computer - IP o nome di dominio per la richiesta
#-quiet - per ricevere solo un valore booleano
$PictureBox.location = New-Object System.Drawing.Point(235,12)
if ((test-connection -Count 1 -computer ya.ru -quiet) -eq $True) {
	$PictureBox.imageLocation = "C:Testyes.png" #L'oggetto accede all'immagine corrispondente 
}
Else {
	$PictureBox.imageLocation = "C:Testno.png" #L'oggetto accede all'immagine corrispondente 
}
$PictureBox.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::zoom

$PictureBox1 = New-Object system.Windows.Forms.PictureBox #L'oggetto per visualizzare le immagini si chiama in modo logico
$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:Testyes.png" #L'oggetto accede all'immagine corrispondente 
}
Else {
	$PictureBox1.imageLocation = "C:Testno.png" #L'oggetto accede all'immagine corrispondente 
}
$PictureBox1.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::zoom

$PictureBox2 = New-Object system.Windows.Forms.PictureBox #L'oggetto per visualizzare le immagini si chiama in modo logico
$PictureBox2.width = 10
$PictureBox2.height = 10
$PictureBox2.location = New-Object System.Drawing.Point(235,52)
if ((test-connection -Count 1 -computer 192.168.x.x -quiet) -eq $True) {
	$PictureBox2.imageLocation = "C:Testyes.png" #L'oggetto accede all'immagine corrispondente 
}
Else {
	$PictureBox2.imageLocation = "C:Testno.png" #L'oggetto accede all'immagine corrispondente 
}
$PictureBox2.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::zoom

$PictureBox3 = New-Object system.Windows.Forms.PictureBox #L'oggetto per visualizzare le immagini si chiama in modo logico
$PictureBox3.width = 10
$PictureBox3.height = 10
$PictureBox3.location = New-Object System.Drawing.Point(235,72)
if ((test-connection -Count 1 -computer 192.168.x.x -quiet) -eq $True) {
	$PictureBox3.imageLocation = "C:Testyes.png" #L'oggetto accede all'immagine corrispondente 
}
Else {
	$PictureBox3.imageLocation = "C:Testno.png" #L'oggetto accede all'immagine corrispondente 
}
$PictureBox3.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::zoom

$PictureBox4 = New-Object system.Windows.Forms.PictureBox #L'oggetto per visualizzare le immagini si chiama in modo logico
$PictureBox4.width = 10
$PictureBox4.height = 10
$PictureBox4.location = New-Object System.Drawing.Point(235,92)
if ((test-connection -Count 1 -computer 10.0.x.x -quiet) -eq $True) {
	$PictureBox4.imageLocation = "C:Testyes.png" #L'oggetto accede all'immagine corrispondente 
}
Else {
	$PictureBox4.imageLocation = "C:Testno.png" #L'oggetto accede all'immagine corrispondente 
}
$PictureBox1.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::zoom

$PictureBox5 = New-Object system.Windows.Forms.PictureBox #L'oggetto per visualizzare le immagini si chiama in modo logico
$PictureBox5.width = 10
$PictureBox5.height = 10
$PictureBox5.location = New-Object System.Drawing.Point(235,112)
if ((test-connection -Count 1 -computer 162.102.x.x -quiet) -eq $True) {
	$PictureBox5.imageLocation = "C:Testyes.png" #L'oggetto accede all'immagine corrispondente 
	}
Else {
	$PictureBox5.imageLocation = "C:Testno.png" #L'oggetto accede all'immagine corrispondente 
	}
$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 = "Ricarica"

# Colleghiamo all'evento di pressione del pulsante l'accesso a ciascun PictureBox secondo la logica descritta in precedenza
$Button.Add_Click({ 
	if ((Test-Connection -Count 1 -computer ya.ru -quiet) -eq $True)
		{$PictureBox.imageLocation	= "C:Testyes.png"}
	Else {$PictureBox.imageLocation	= "C:Testno.png"}
	  
	if ((Test-Connection -Count 1 -computer 8.8.8.8 -quiet) -eq $True)
		{$PictureBox1.imageLocation	= "C:Testyes.png"}
	Else {$PictureBox1.imageLocation	= "C:Testno.png"}

	if ((Test-Connection -Count 1 -computer 192.168.x.x -quiet) -eq $True)
		{$PictureBox2.imageLocation	= "C:Testyes.png"}
	Else {$PictureBox2.imageLocation	= "C:Testno.png"}

	if ((Test-Connection -Count 1 -computer 192.168.x.x -quiet) -eq $True)
		{$PictureBox3.imageLocation	= "C:Testyes.png"}
	Else {$PictureBox3.imageLocation	= "C:Testno.png"}

	if ((Test-Connection -Count 1 -computer 10.0.x.x -quiet) -eq $True)
		{$PictureBox4.imageLocation	= "C:Testyes.png"}
	Else {$PictureBox4.imageLocation	= "C:Testno.png"}

	if ((Test-Connection -Count 1 -computer 162.102.x.x -quiet) -eq $True)
		{$PictureBox5.imageLocation	= "C:Testyes.png"}
	Else {$PictureBox5.imageLocation	= "C:Testno.png"}
	})

$main_form.Controls.Add($Label) #aggiungiamo l'oggetto creato al modulo, affinché non venga perso durante l'esecuzione dello script
$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() #Chiamiamo la finestra di dialogo elementare

Anche mantenendo la pulizia e rispettando la struttura, la revisione periodica provocherà sensazioni spiacevoli.

Per iniziare, separiamo il controllo della disponibilità in una funzione e il percorso della directory in una variabile:

$script_path	= "C:TestPS ping"

#Trasferiamo nella funzione l'oggetto PictureBox già creato e l'indirizzo IP che deve essere verificato.
#In uscita cambierà l'immagine caricata.
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"} 
	}

Estraiamo i dati sull'host in un file esterno path.txt, registrandoli nel formato «ip/host-nome-funzionale/», e nel documento li accetteremo in array. Inoltre, rendiamo il calcolo della posizione Y più automatizzato. Tutto ciò ci permette di creare Label e checkbox chiamando la funzione:

Monitoraggio della disponibilità degli host con Powershell

#создаем описательную линию, на вход идут: объект 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
	}

Aggiungiamo uno spazio per visualizzare l'ora dell'ultima verifica, perché è comodo, e completiamo leggermente l'azione al clic del pulsante.

Monitoraggio della disponibilità degli host con Powershell

$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 
	})

Ho anche aggiunto una piccola funzionalità che, quando rileva un host non disponibile, non solo cambia l'indicatore, ma grida anche dagli altoparlanti.

Add-Type -AssemblyName System.Speech
$voice	= New-Object System.Speech.Synthesis.SpeechSynthesizer
$voice.Rate	= 5
$voice.Speak("Attenzione! Attenzione! Il sistema è sotto attacco!")

Dopo alcuni abbellimenti e sistemazioni per renderlo leggibile e comodo, è venuto così:

Codice completo dello script

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

#Spostiamo nella funzione già creata l'oggetto PictureBox e l'indirizzo IP da controllare.
#In uscita cambia l'immagine caricata.
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("Errore! Host " + $path_ip + ", non disponibile!")
		}
	}

#creiamo una linea descrittiva, in ingresso: oggetto Label, indirizzo IP, descrizione e posizione sull'asse 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
	}

#creiamo un indicatore per la linea descrittiva, in ingresso: oggetto PictureBox, indirizzo IP e posizione sull'asse 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 ='Collegamenti attivi' #Nome nella intestazione
$main_form.Width = 300 #Larghezza della finestra
$main_form.Height = 200 #Altezza della finestra
$main_form.AutoSize = $true #Rendiamo la dimensione del modulo adattabile
$main_form.TopMost	= $true #Questa è un'opzione molto importante, consente di tenere la finestra sopra le altre

$line = Get-content -LiteralPath $script_path"path.txt" #estraiamo i dati sugli host necessari
$len = $line.Length	#calcoliamo la lunghezza, precisamente l'array delle lunghezze di ogni riga

$i = 0

#dichiarare arrays necessari per il seguito
$ip	= @()	#array ip
$capt	= @()	#array descrizione
$Labels	=@()	#array Label
$PictureBoxs	=@()	#array PictureBox

while($i -lt $len){
	$f	= $line[$i].IndexOf("/") #calcoliamo la posizione di inizio della descrizione
	$l	= $line[$i].LastIndexOf("/")	#calcoliamo la posizione di fine della descrizione
	$ip	+= $line[$i].Substring(0,$f)	#estraiamo l'ip
	$capt	+= $line[$i].Substring($f+1,$l-$f-1)	#estraiamo la descrizione

	#creiamo un campo Label
	Create_line -label ($label_obj = New-Object System.Windows.Forms.Label) -path_ip $ip[$i] -caption $capt[$i] -top $label_from_top
	#creiamo un campo PictureBox
	Create_link -PictureBox ($PictureBox_obj = New-Object system.Windows.Forms.PictureBox) -path_ip $ip[$i] -top $label_from_top

	$label_from_top	+= 15	#incrementiamo l'asse Y

	$Labels	+= $label_obj	#inseriamo il Label creato nell'array totale
	$PictureBoxs	+= $PictureBox_obj	#inseriamo il PictureBox creato nell'array totale
	$main_form.Controls.Add($Labels[$i])
	$main_form.Controls.Add($PictureBoxs[$i])
	$i	+=1
}

#questo campo mostra l'ultimo tempo di controllo
$Label0	= New-Object System.Windows.Forms.Label
$Label0.Text	= Get-Date
$Label0.Location	= New-Object System.Drawing.Point(80,180)
$Label0.AutoSize	= $true


# Colleghiamo un evento di pressione del pulsante per ciascun PictureBox secondo la logica precedentemente descritta
$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	= "Ricarica"

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

Epifania

Spero che questo tutorial sia utile a qualcuno. Se siete già esperti in materia, vi faccio i complimenti, io non lo sono. Ma sono pronto ad ascoltare i vostri commenti e suggerimenti.

È stato piacevole per me esplorare e assemblare questa piccola, ma utile utility. Ho in programma di implementare anche l'aggiunta e la rimozione di nodi tramite GUI, oltre a realizzare ciò che doveva essere fatto per primo: l'aggiornamento automatico degli stati senza la necessità di premere un pulsante, affinché non blocchi 'powershell.exe'.

L'ultima versione dello script è su GitHub

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster