Monitorování dostupnosti hostitelů pomocí Powershell

Dobrý den všem, chtěl bych se podělit o jednoduchý návod "Jak přestat ručně pingovat desítky hostitelů. Bez registrace a SMS!".

Monitorování dostupnosti hostitelů pomocí PowershellZ hlubin Internetu

Je důležité: nejsem programátor ani systémový administrátor, ale musím pracovat současně s velkým množstvím servery a služeb, tento skript jsem napsal pro vlastní pohodlí.

Všechny, kterým by to mohlo být užitečné, zvu k pokračování.

Proč PowershellMám zkušenosti se psaním jednoduchých programů v Pythonu, ale vyžaduje buď nainstalovaný interpretr, nebo oprávnění ke spuštění .exe, což v rámci mé práce není vždy možné. Skript v Powershellu se ale častěji podaří spustit.

Ne všichni mají rádi konzoli/terminál

Myslím, že v tom není rozpor, jinak by všichni stále používali konzolové e-mailové klienty a v *nix systémech by se neobjevil GUI.

Jelikož běžně používám Powershell poměrně primitivně, snažil jsem se nejdříve pochopit, zda k němu lze připojit GUI. Ukazuje se, že ano, a docela jednoduše:

Monitorování dostupnosti hostitelů pomocí Powershell

Add-Type -assembly System.Windows.Forms # Připojíme knihovnu
$main_form = New-Object System.Windows.Forms.Form # Vytvoříme objekt s naším "oknem"

# Určíme parametry
$main_form.Text ='Odkazy nahoru' # Jméno v záhlaví
$main_form.Width = 300 # Šířka okna
$main_form.Height = 200 # Výška okna
$main_form.AutoSize = $true # Dáme mu možnost měnit velikost, pokud je to potřeba
$main_form.ShowDialog() # Vyvoláme "okno"

Přidáme k tomu výstupní prvek a dostaneme elementární Windows okno tautologie?.

Monitorování dostupnosti hostitelů pomocí Powershell

Add-Type -assembly System.Windows.Forms # Připojíme knihovnu

$main_form = New-Object System.Windows.Forms.Form # Vytvoříme proměnnou pro naše "okno"

# Nastavíme pro něj parametry
$main_form.Text ='Odkazy nahoře' # Název v záhlaví
$main_form.Width = 300 # Šířka okna
$main_form.Height = 200 # Výška okna
$main_form.AutoSize = $true # Umožníme mu automaticky měnit velikost, pokud bude potřeba

$Label = New-Object System.Windows.Forms.Label # Všechny prvky formy budou uloženy do proměnných, ale ve skutečnosti to jsou objekty jako jakékoli jiné proměnné v PowerShellu
$Label.Text = "Ahoj! Já jsem základní Windows okno, a co jsi dokázal ty?" # Výstupní text
$Label.Location  = New-Object System.Drawing.Point(10,65) # Umístění objektu uvnitř formy na horizontále a vertikále (x,y)
$Label.AutoSize = $true 

$main_form.Controls.Add($Label) # Přidáme vytvořený objekt k formě, aby se neztratil během provádění skriptu

$main_form.ShowDialog() # Vyvoláme základní okno

Přidáme dynamiku

Nástroj, kterým jsem pingoval Yandex a připojoval *.iso, nyní má samostatné GUI, ale to nestačí. Tímto způsobem lze zobrazit informace o dostupnosti, ale pro monitorování bude nutné každý krát restartovat skript.

Nejprve nakreslíme dvě ikony a přidáme možnost zobrazovat obrázky.

Monitorování dostupnosti hostitelů pomocí Powershell

$PictureBox = New-Object system.Windows.Forms.PictureBox # Objekt pro zobrazení obrázků se nazývá docela logicky
$PictureBox.width = 10
$PictureBox.height = 10
$PictureBox.location = New-Object System.Drawing.Point(178,12)

# Tady už přecházíme k věci, připojujeme zobrazovaný obrázek k výsledku kontroly dostupnosti uzlu pomocí cmdletu
#<b>test-connection</b>, kde:
#-Count - předá počet požadavků
#-computer - IP adresa nebo doménové jméno pro požadavek
#-quiet - aby nám vrátilo pouze Boolean hodnotu
if ((test-connection -Count 1 -computer ya.ru -quiet) -eq $True) {
	$PictureBox.imageLocation = "C:Testyes.png" # Objekt odkazuje na odpovídající obrázek 
}
Else {
	$PictureBox.imageLocation = "C:Testno.png" # Objekt odkazuje na odpovídající obrázek 
}
$PictureBox.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::zoom

$main_form.Controls.Add($PictureBox)

Opět nám DNS servery dělají problémy…

Monitorování dostupnosti hostitelů pomocí Powershell
A také přidáme tlačítko, aby bylo možné aktualizovat hodnoty.

Monitorování dostupnosti hostitelů pomocí 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 = "Obnovit"

# Na událost kliknutí tlačítka připojíme každému PictureBoxu podle dříve popsané logiky
$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)

Monitorování dostupnosti hostitelů pomocí Powershell

Skvělé, teď do produkce!?

Ručním napsáním přibližně půl tuctu hostitelů jsem si náhle uvědomil jednu věc — tento projekt skončí, hostitelé se změní a já budu muset pokaždé upravit skript. Z jedné strany, nic strašného, je to přece řešení pro mě milovaného. Z druhé strany, to řešení pro mě milovaného, podívejte se, co se vlastně děje:

Pohled pro slabé povahy

Add-Type -assembly System.Windows.Forms # Připojíme knihovnu

$main_form = New-Object System.Windows.Forms.Form # Vytvoříme proměnnou s naším "oknem"

# Nastavíme pro něj parametry prostřednictvím parametrů
$main_form.Text ='Odkazy nahoře' # Název v záhlaví
$main_form.Width = 300 # Šířka okna
$main_form.Height = 200 # Výška okna
$main_form.AutoSize = $true # Umožníme mu samostatně měnit velikost, když je to potřeba

$Label = New-Object System.Windows.Forms.Label # Všechny prvky formuláře budou uloženy do proměnných, ale ve skutečnosti to jsou objekty, jako každé jiné proměnné v Powershell
$Label.Text = "ya.ru		............................" # Vypisovaný text 
$Label.Location  = New-Object System.Drawing.Point(15,10) # Umístění objektu uvnitř formuláře horizontálně a vertikálně (x,y)
$Label.AutoSize = $true 

$Label1 = New-Object System.Windows.Forms.Label # Všechny prvky formuláře budou uloženy do proměnných, ale ve skutečnosti to jsou objekty, jako každé jiné proměnné v Powershell
$Label1.Text = "8.8.8.8		............................" # Vypisovaný text googlovského DNS
$Label1.Location  = New-Object System.Drawing.Point(15,30) # Umístění objektu uvnitř formuláře horizontálně a vertikálně (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 # Objekt pro zobrazení obrázků je pojmenován docela logicky
$PictureBox.width = 10
$PictureBox.height = 10

# Tady se dostáváme k věci, připojujeme zobrazený obrázek k výsledku kontroly dostupnosti uzlu pomocí cmdletu
#<b>test-connection</b>, kde:
#-Count - předává počet požadavků
#-computer - IP adresa nebo doménové jméno pro požadavek
#-quiet - aby nám vrátilo pouze Boolean hodnotu
$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" # Objekty se odkazují na odpovídající obrázek 
}
Else {
	$PictureBox.imageLocation = "C:Testno.png" # Objekty se odkazují na odpovídající obrázek 
}
$PictureBox.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::zoom

$PictureBox1 = New-Object system.Windows.Forms.PictureBox # Objekt pro zobrazení obrázků se nazývá celkem logicky
$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" # Objekty se odkazují na odpovídající obrázek 
}
Else {
	$PictureBox1.imageLocation = "C:Testno.png" # Objekty se odkazují na odpovídající obrázek 
}
$PictureBox1.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::zoom

$PictureBox2 = New-Object system.Windows.Forms.PictureBox # Objekt pro zobrazení obrázků se nazývá celkem logicky
$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" # Objekty se odkazují na odpovídající obrázek 
}
Else {
	$PictureBox2.imageLocation = "C:Testno.png" # Objekty se odkazují na odpovídající obrázek 
}
$PictureBox2.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::zoom

$PictureBox3 = New-Object system.Windows.Forms.PictureBox # Objekt pro zobrazení obrázků se nazývá celkem logicky
$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" # Objekty se odkazují na odpovídající obrázek 
}
Else {
	$PictureBox3.imageLocation = "C:Testno.png" # Objekty se odkazují na odpovídající obrázek 
}
$PictureBox3.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::zoom

$PictureBox4 = New-Object system.Windows.Forms.PictureBox # Objekt pro zobrazení obrázků se nazývá celkem logicky
$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" # Objekty se odkazují na odpovídající obrázek 
}
Else {
	$PictureBox4.imageLocation = "C:Testno.png" # Objekty se odkazují na odpovídající obrázek 
}
$PictureBox1.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::zoom

$PictureBox5 = New-Object system.Windows.Forms.PictureBox # Objekt pro zobrazení obrázků se nazývá celkem logicky
$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" # Objekty se odkazují na odpovídající obrázek 
	}
Else {
	$PictureBox5.imageLocation = "C:Testno.png" # Objekty se odkazují na odpovídající obrázek 
	}
$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"

# Vytváříme událost kliknutí na tlačítko pro vyvolání každého PictureBox podle dříve popsané logiky
$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) # přidáme vytvořený objekt do formuláře, aby nezmizel při vykonávání skriptu
$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() # Vyvoláme jednoduše elementární okno

I když se dodržuje pořádek a struktura, občasné úpravy budou vyvolávat nepříjemné pocity.

Nejprve přesuneme kontrolu dostupnosti do samostatné funkce a cestu k adresáři do samostatné proměnné:

$script_path	= "C:TestPS ping"

# Přesuneme se do funkce již vytvořeného objektu PictureBox a IP adresy, kterou je třeba zkontrolovat.
# Na výstupu se změní načítaný obrázek.
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"} 
	}

Přesuneme údaje o hostiteli do externího souboru path.txt, zapisujeme ve formátu „ip/host-funkční-jméno/“, a v dokumentu je budeme přijímat jako pole. Také učiníme výpočet polohy po Y více automatizovaným. To nám dává možnost vytvářet Labely a checkboxy voláním funkce:

Monitorování dostupnosti hostitelů pomocí 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
	}

Přidáme místo pro zobrazení času poslední kontroly, protože je to praktické, a mírně doplníme akci při stisknutí tlačítka.

Monitorování dostupnosti hostitelů pomocí 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 
	})

Také jsem připojil malou funkci, která při zjištění nedostupného hostitele oznamovala nejen změnou indikátoru, ale také křičela ze reproduktorů.

Add-Type -AssemblyName System.Speech
$voice	= New-Object System.Speech.Synthesis.SpeechSynthesizer
$voice.Rate	= 5
$voice.Speak("Varování! Varování! Základna je pod útokem!")

Takže po několika vylepšeních a úpravách k čitelnějšímu a pohodlnějšímu vzhledu to vypadá takto:

Úplný kód skriptu

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

# Přesuneme do funkce již vytvořený objekt PictureBox a IP adresu, kterou je třeba zkontrolovat.
# Jako výstup měníme načítaný obrázek.
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("Chyba! Host " + $path_ip + ", není dostupný!")
		}
	}

# Vytváříme popisnou čáru, na vstupu jsou: objekt Label, IP adresa, popis a pozice na ose 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
	}

# Vytváříme indikátor pro popisnou čáru, na vstupu jsou: objekt PictureBox, IP adresa a pozice na ose 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 ='Odkazy aktivní' # Název v záhlaví
$main_form.Width = 300 # Šířka okna
$main_form.Height = 200 # Výška okna
$main_form.AutoSize = $true # Dáváme mu možnost se automaticky měnit, pokud je to potřeba
$main_form.TopMost	= $true # Toto je velmi důležité, umožňuje to přichytit okno nad ostatní

$line = Get-content -LiteralPath $script_path"path.txt" # Vytahujeme data o potřebných hostech
$len = $line.Length	# Vypočítáme délku, a přesněji pole délky každého řádku

$i = 0

# Dále deklarujeme pole, která budou potřebná dále
$ip	= @()	# pole ip
$capt	= @()	# pole popisu
$Labels	=@()	# pole Label
$PictureBoxs	=@()	# pole PictureBox

while($i -lt $len){
	$f	= $line[$i].IndexOf("/") # Vypočítáme pozici začátku popisu
	$l	= $line[$i].LastIndexOf("/")	# Vypočítáme pozici konce popisu
	$ip	+= $line[$i].Substring(0,$f)	# Vytahujeme ip
	$capt	+= $line[$i].Substring($f+1,$l-$f-1)	# Vytahujeme popis

	# Vytváříme pole Label
	Create_line -label ($label_obj = New-Object System.Windows.Forms.Label) -path_ip $ip[$i] -caption $capt[$i] -top $label_from_top
	# Vytváříme pole PictureBox
	Create_link -PictureBox ($PictureBox_obj = New-Object system.Windows.Forms.PictureBox) -path_ip $ip[$i] -top $label_from_top

	$label_from_top	+= 15	# Děláme "krok" po ose Y

	$Labels	+= $label_obj	# Přidáváme vytvořený Label do celkového pole
	$PictureBoxs	+= $PictureBox_obj	# Přidáváme vytvořený PictureBox do celkového pole
	$main_form.Controls.Add($Labels[$i])
	$main_form.Controls.Add($PictureBoxs[$i])
	$i	+=1
}

# Toto pole s posledním časem kontroly
$Label0	= New-Object System.Windows.Forms.Label
$Label0.Text	= Get-Date
$Label0.Location	= New-Object System.Drawing.Point(80,180)
$Label0.AutoSize	= $true


# Připojujeme událost kliknutí na každé PictureBox podle dříve popsané logiky
$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	= "Obnovit"

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

Poznámka na závěr

Doufám, že bude tento tutoriál někomu užitečný. Pokud jste s tímto tématem už od kolébky, gratuluji, já to nedělal. Ale jsem ochoten vyslechnout vaše komentáře a návrhy.

Pro mě osobně bylo příjemné si pohrát a sestavit takovou malou, ale užitečnou utilitu. Mám v plánu implementovat přidávání a odstraňování uzlů z GUI a také udělat to, co mělo být realizováno jako první — automatickou aktualizaci stavů bez potřeby klikat na tlačítko, aby to nezamrzalo "powershell.exe".

Poslední verze skriptu na GitHub

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster