Blog (9)
Komentarze (978)
Recenzje (1)

Powershell to nie tylko konsola, czyli aplikacja graficzna w POSHu

@FaUstPowershell to nie tylko konsola, czyli aplikacja graficzna w POSHu07.05.2016 14:48

Tytułem wstępu

uwaga dużo tekstu, jak chcesz obrazki poszukaj gdzie indziej ;)

Każdy obeznany z obecnymi technologiami spotkał się z Powershellem. Administratorzy Windowsów kochają (albo jeszcze nie znają), admini Linuxów podśmiechują się z politowaniem, a zwykli użytkownicy uważają za czarną magię. Wpis ma na celu pokazanie jak w miarę łatwo i przystępnie można ubrać skrypty w Windowsowe GUI i ułatwić sobie pracę z powłoką wymyśloną przez Microsoft.

Uwaga - jeśli nigdy nie miałeś styczności z POSHem, przestudiuj manuale oraz inne wpisy (np ten stworzony przez bachusa)

Na warsztat weźniemy sobie upierdliwą niedoróbkę Windowsa 10 - zmiana bramy domyślnej przy korzystaniu z VPNa. W poprzednich wersjach wystarczyło zaznaczyć odpowiedni checkbox w ustawieniach połączenia i na tym koniec. W 10 wersji okienek już tego nie uświadczymy. Aby dokonać zmiany należy wydać polecenie:

Set-VPNCnnection -name {nazwa_polaczenia} -SplitTunelling {$true/$false}

gdzie $true oznacza separację ruchu czyli używanie bramy z połączenia lokalnego, a $false wyłączy separację i cały ruch będzie przebiegał przez bramę zdefiniowaną w VPNie.

Łatwo co? Gorzej jeśli posiadamy kilka połączeń którymi trzeba żonglować i często zmieniać ich ustawienia, lub z VPNa korzysta nieobeznana osoba.

W tym właśnie celu przygotujemy prostą aplikację z GUI.

Tworzymy interfejs

Interfejs można zaprogramować, jak w każdym środowisku w czystym kodzie, ale (zwłaszcza dla niewprawionych osób) jest to mordęga i okazja do przypomnienia sobie wszystkich znanych przekleństw. Istnieje kilka rozwiązań WYSWIG dla Powershella. Podczas tworzenia wpisu skorzystałem z Admin Script Editor który jest darmowy i do tworzenia interfejsu oraz kodu wystarczy. Istnieją aplikacje komercyjne, takie jak PrimalForms które potrafią o wiele więcej, lecz kosztują też odpowiednio więcej.

Główne okno ASE po stworzeniu projektu wygląda następująco:

Możemy przejść do tworzenia interfejsu (Tool -> ScriptForm Designer). Każdy kto miał do czynienia ze środowiskami programistycznymi typu Visual Studio szybko się tutaj odnajdzie.

Tworzymy takie oto okienko:

Pododawajmy akcje do przycisków, comboboxa oraz ustawmy atrybuty okna:

Gdy już wszystko mamy gotowe wciskamy CTRL+E i przechodzimy do edytora tekstowego gdzie mamy gotowy kod. Kod interfejsu wygląda następująco:


#region ScriptForm Designer

#region Constructor

[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")

#endregion

#region Post-Constructor Custom Code

#endregion

#region Form Creation
#Warning: It is recommended that changes inside this region be handled using the ScriptForm Designer.
#When working with the ScriptForm designer this region and any changes within may be overwritten.
#~~< Form1 >~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$Form1 = New-Object System.Windows.Forms.Form
$Form1.AutoSize = $true
$Form1.ClientSize = New-Object System.Drawing.Size(292, 104)
$Form1.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedDialog
$Form1.MaximizeBox = $false
$Form1.Text = "Set default VPN gateway"
#~~< btnSplitDisable >~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$btnSplitDisable = New-Object System.Windows.Forms.Button
$btnSplitDisable.Enabled = $false
$btnSplitDisable.Location = New-Object System.Drawing.Point(160, 64)
$btnSplitDisable.Size = New-Object System.Drawing.Size(112, 23)
$btnSplitDisable.TabIndex = 4
$btnSplitDisable.Text = "ENABLE"
$btnSplitDisable.UseVisualStyleBackColor = $true
$btnSplitDisable.add_Click({btnSplitDisable_click($btnSplitDisable)})
#~~< btnSplitEnable >~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$btnSplitEnable = New-Object System.Windows.Forms.Button
$btnSplitEnable.Enabled = $false
$btnSplitEnable.Location = New-Object System.Drawing.Point(16, 64)
$btnSplitEnable.Size = New-Object System.Drawing.Size(112, 23)
$btnSplitEnable.TabIndex = 3
$btnSplitEnable.Text = "DISABLE"
$btnSplitEnable.UseVisualStyleBackColor = $true
$btnSplitEnable.add_Click({btnSplitEnable_click($btnSplitEnable)})
#~~< lblSplitTunellingStatus >~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$lblSplitTunellingStatus = New-Object System.Windows.Forms.Label
$lblSplitTunellingStatus.Location = New-Object System.Drawing.Point(16, 32)
$lblSplitTunellingStatus.Size = New-Object System.Drawing.Size(256, 23)
$lblSplitTunellingStatus.TabIndex = 2
$lblSplitTunellingStatus.Text = ""
$lblSplitTunellingStatus.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter
#~~< Label1 >~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$Label1 = New-Object System.Windows.Forms.Label
$Label1.Location = New-Object System.Drawing.Point(10, 8)
$Label1.Size = New-Object System.Drawing.Size(64, 23)
$Label1.TabIndex = 1
$Label1.Text = "Select vpn:"
$Label1.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter
#~~< cbVPNName >~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$cbVPNName = New-Object System.Windows.Forms.ComboBox
$cbVPNName.FormattingEnabled = $true
$cbVPNName.Location = New-Object System.Drawing.Point(74, 8)
$cbVPNName.SelectedIndex = -1
$cbVPNName.Size = New-Object System.Drawing.Size(200, 21)
$cbVPNName.TabIndex = 0
$cbVPNName.Text = ""
$cbVPNName.add_SelectedIndexChanged({cbVPNName_changed($cbVPNName)})
$Form1.Controls.Add($btnSplitDisable)
$Form1.Controls.Add($btnSplitEnable)
$Form1.Controls.Add($lblSplitTunellingStatus)
$Form1.Controls.Add($Label1)
$Form1.Controls.Add($cbVPNName)

#endregion

Jak widać wszystko jest czytelne i ładnie opisane. Linie


[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")

informują interpreter że ma załadować biblioteki Windows.Forms oraz Drawing które odpowiadają za obsługę okienek w POSHu.

Funkcje

Interfejs już mamy to go oprogramujmy. Poniżej podanego kodu (sekcja custom code stworzona przez ASE) dodajmy:


$VPN = Get-VpnConnection | select name
foreach ($vpnname in $VPN)
{
	$cbVPNName.Items.Add($vpnname.name)
}

Kod ma za zadanie pobrać do zmiennej $VPN nazwy wszystkich połączeń zawartych w systemie i za pomocą pętli dodać wszystkie nazwy do listy wyboru

Ważne aby powyższa pętla znajdowała się w tym miejscu, czyli przed uruchomieniem formularza. Za uruchomienie formatki odpowiada funkcja Main którą znajdziemy poniżej.

Pozostaje nam oprogramować dodane przy tworzeniu formularza zdarzenia. Na pierwszy ogień kod który uruchomi się przy zmianie danych w liście wyboru (wybranie nazwy z listy, bądź wpisanie innego tekstu) :


function cbVPNName_changed($object){
	try
	{
		$selectedVPN = $cbVPNName.SelectedItem
		$status = Get-VPNConnection -name $selectedVPN
		if ($status.SplitTunneling -eq $true)
		{
			$lblSplitTunellingStatus.Text = "VPN isn't a default gateway"
			$btnSplitEnable.Enabled = $false
			$btnSplitDisable.Enabled = $true
		}
		elseif ($status.SplitTunneling -eq $false)
		{
			$lblSplitTunellingStatus.Text = "VPN is a default gateway"
			$btnSplitEnable.Enabled = $true
			$btnSplitDisable.Enabled = $false
		}
	}
	catch
	{
		[System.Windows.Forms.MessageBox]::Show("VPN connection do not exist", "Error", "OK", "Error")
	}
}

Kod ma za zadanie pobrać nazwę połączenia VPN z listy, sprawdzić czy dla połączenia jest włączony SplitTunelling, wyświetlić odpowiedni status i odpowiedni włączyć/wyłączyć przyciski.

2 pozostałe funkcje odpowiadają za obsługę przycisków ustawiających właściwości połączenia:


function btnSplitDisable_click( $object ){
	try
	{
		$selectedVPN = $cbVPNName.SelectedItem
		set-VpnConnection -name $selectedVPN -SplitTunneling $false
		$lblSplitTunellingStatus.Text = "VPN is a default gateway"
		$btnSplitDisable.Enabled = $false
		$btnSplitEnable.Enabled = $true
	}
	catch
	{
		[System.Windows.Forms.MessageBox]::Show("VPN connection do not exist", "Error", "OK", "Error")
	}
	
}

function btnSplitEnable_click( $object ){
	try
	{
		$selectedVPN = $cbVPNName.SelectedItem
		set-VpnConnection -name $selectedVPN -SplitTunneling $true
		$lblSplitTunellingStatus.Text = "VPN isn't a default gateway"
		$btnSplitEnable.Enabled = $false
		$btnSplitDisable.Enabled = $true
	}
	catch
	{
		[System.Windows.Forms.MessageBox]::Show("VPN connection do not exist", "Error", "OK", "Error")
	}
		
}

Kod obu przycisków jest podobny więc przedstawię schemat działania obydwu:

  • przypisz do zmiennej $selectedVPN nazwę połączenia VPN,
  • ustaw status połączenia którego nazwę zapisaliśmy w zmiennej $selectedVPN
  • ustaw odpowiedni status w polu etykiety
  • wyłącz/włącz dany przycisk

W kodzie zdarzeń użyłem prostej obsługi błędów, czyli konstukcji try, catch. W bloku try znajduje się kod służący do obsługi programu, natomiast catch zostaje wyzwolone w momencie gdy pojawi się błąd (niepoprawne dane, zły format etc). W powyższym przypadku otrzymamy komunikat że połączenie o nazwie jaką wpisaliśmy do Combo Boxa nie istnieje w systemie. Możemy zamiast tego przekierować błąd do dziennika, wywołać inny skrypt itp. Cała skrypt znajduje się tutaj. Zrób z nim co chcesz, ale jeśli wykorzystasz kod w innym dostępnym publicznie rozwiązaniu wklej link w komentarzu :)

Tak w skrócie wygląda tworzenie okienkowej aplikacji w Powershellu. Możliwości jego wykorzystania jest sporo - możemy np ułatwić sobie administrację AD, MS Exchange, czy też VMWare'e, ogranicza nas tylko wiedza i możliwości poszczególnych funkcji PSa. Jeśli przebrnąłeś przez ścianę tekstu gratuluję, jeśli nie spróbuj ponownie ;)

Szanowna Użytkowniczko! Szanowny Użytkowniku!
×
Aby dalej móc dostarczać coraz lepsze materiały redakcyjne i udostępniać coraz lepsze usługi, potrzebujemy zgody na dopasowanie treści marketingowych do Twojego zachowania. Twoje dane są u nas bezpieczne, a zgodę możesz wycofać w każdej chwili na podstronie polityka prywatności.

Kliknij "PRZECHODZĘ DO SERWISU" lub na symbol "X" w górnym rogu tej planszy, jeżeli zgadzasz się na przetwarzanie przez Wirtualną Polskę i naszych Zaufanych Partnerów Twoich danych osobowych, zbieranych w ramach korzystania przez Ciebie z usług, portali i serwisów internetowych Wirtualnej Polski (w tym danych zapisywanych w plikach cookies) w celach marketingowych realizowanych na zlecenie naszych Zaufanych Partnerów. Jeśli nie zgadzasz się na przetwarzanie Twoich danych osobowych skorzystaj z ustawień w polityce prywatności. Zgoda jest dobrowolna i możesz ją w dowolnym momencie wycofać zmieniając ustawienia w polityce prywatności (w której znajdziesz odpowiedzi na wszystkie pytania związane z przetwarzaniem Twoich danych osobowych).

Od 25 maja 2018 roku obowiązuje Rozporządzenie Parlamentu Europejskiego i Rady (UE) 2016/679 (określane jako "RODO"). W związku z tym chcielibyśmy poinformować o przetwarzaniu Twoich danych oraz zasadach, na jakich odbywa się to po dniu 25 maja 2018 roku.

Kto będzie administratorem Twoich danych?

Administratorami Twoich danych będzie Wirtualna Polska Media Spółka Akcyjna z siedzibą w Warszawie, oraz pozostałe spółki z grupy Wirtualna Polska, jak również nasi Zaufani Partnerzy, z którymi stale współpracujemy. Szczegółowe informacje dotyczące administratorów znajdują się w polityce prywatności.

O jakich danych mówimy?

Chodzi o dane osobowe, które są zbierane w ramach korzystania przez Ciebie z naszych usług, portali i serwisów internetowych udostępnianych przez Wirtualną Polskę, w tym zapisywanych w plikach cookies, które są instalowane na naszych stronach przez Wirtualną Polskę oraz naszych Zaufanych Partnerów.

Dlaczego chcemy przetwarzać Twoje dane?

Przetwarzamy je dostarczać coraz lepsze materiały redakcyjne, dopasować ich tematykę do Twoich zainteresowań, tworzyć portale i serwisy internetowe, z których będziesz korzystać z przyjemnością, zapewniać większe bezpieczeństwo usług, udoskonalać nasze usługi i maksymalnie dopasować je do Twoich zainteresowań, pokazywać reklamy dopasowane do Twoich potrzeb. Szczegółowe informacje dotyczące celów przetwarzania Twoich danych znajdują się w polityce prywatności.

Komu możemy przekazać dane?

Twoje dane możemy przekazywać podmiotom przetwarzającym je na nasze zlecenie oraz podmiotom uprawnionym do uzyskania danych na podstawie obowiązującego prawa – oczywiście tylko, gdy wystąpią z żądaniem w oparciu o stosowną podstawę prawną.

Jakie masz prawa w stosunku do Twoich danych?

Masz prawo żądania dostępu, sprostowania, usunięcia lub ograniczenia przetwarzania danych. Możesz wycofać zgodę na przetwarzanie, zgłosić sprzeciw oraz skorzystać z innych praw wymienionych szczegółowo w polityce prywatności.

Jakie są podstawy prawne przetwarzania Twoich danych?

Podstawą prawną przetwarzania Twoich danych w celu świadczenia usług jest niezbędność do wykonania umów o ich świadczenie (tymi umowami są zazwyczaj regulaminy). Podstawą prawną przetwarzania danych w celu pomiarów statystycznych i marketingu własnego administratorów jest tzw. uzasadniony interes administratora. Przetwarzanie Twoich danych w celach marketingowych realizowanych przez Wirtualną Polskę na zlecenie Zaufanych Partnerów i bezpośrednio przez Zaufanych Partnerów będzie odbywać się na podstawie Twojej dobrowolnej zgody.