Strona używa cookies (ciasteczek). Dowiedz się więcej o celu ich używania i zmianach ustawień. Korzystając ze strony wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki.    X

Powershell to nie tylko konsola, czyli aplikacja graficzna w POSHu

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

windows porady programowanie

Komentarze

0 nowych
GBM MODERATOR BLOGA  20 #1 07.05.2016 14:03

Ta obiektowość w PowerShellu, sprawia naprawdę fajne wrażenie :)

AntyHaker   18 #2 07.05.2016 21:46

Nie wiem o co chodzi, ale samo wykonanie wpisu mistrzostwo :D Oby więcej tego typu rzeczy.

Semtex   18 #3 07.05.2016 21:50

Faust jak chce to potrafi ;) Dobra robota.

  #4 08.05.2016 01:56

Zmarnowany potencjał.
Artykuł jest dosłownie o niczym.
Nie ma sensu ubierać poleceń w szatę graficzną.
Fragment, który wspomina o osobie nieobeznanej..
Już widzę, jak osoby nieobeznane pchają się do używania VPN.
Jak już ktoś wie, co to jest, wie jak sobie z tym poradzić.

To jak Tworzenie szaty graficznej dla pozostałych poleceń konsoli.
Można? Można. Trzeba? Nie, nie trzeba. Bo po co?

Sztuka dla sztuki. Ot co.

drobok   14 #5 08.05.2016 09:54

@GBM: obiektowość jest od winformsów a nie PS

Fajny wpis, nie wpadłbym na to żeby w okienko ubierać komendy ;)

Autor edytował komentarz w dniu: 08.05.2016 09:57
FaUst   12 #6 08.05.2016 10:26

@drobok: Cały PS jest obiektowy :)

djfoxer   18 #7 08.05.2016 11:17

PS jest bardzo ciekawy i potężny.3 lata temu (dzizas.... jak czas leci) miałem wpis o tym jak tworzyć ręcznie GUI do PS: http://www.dobreprogramy.pl/djfoxer/PowerShell-i-.NET-programowanie-w-konsoli-Wi...

klonek_wp   6 #8 08.05.2016 11:30

ciekawy wpis i czekamy na kolejne, a jak sam wspomniałeś - dziedzin do oskryptowania z PS jest jeszcze sporo ;)

FaUst   12 #9 08.05.2016 11:37

@klonek_wp: Tylko opisywanie kolejnych skryptów byłoby nudne ;)

klonek_wp   6 #10 08.05.2016 11:42

@FaUst: tu się nie zgodzę ;) nie chodzi o sam skrypt ale o ciekawy pomysł na niego - np. wyłapanie która zapadka w AD nie pozwala na coś i opakowane w proste i zrozumiałe GUI

Autor edytował komentarz w dniu: 08.05.2016 11:46
klonek_wp   6 #11 08.05.2016 11:46

@djfoxer: PS. DePesza działa i powiadomienia docierają bez problemu - będzie chwila to może coś na gitubie dorzucę od siebie

  #12 08.05.2016 12:46

Jeśli to jest dużo tekstu, to chyba stary się robię :/

KyRol   18 #13 09.05.2016 02:54

@GBM: Na mnie większe wrażenie sprawia bash w tandemie z zenity;P
http://zenit.senecac.on.ca/wiki/index.php/How_to_Use_Zenity

Autor edytował komentarz w dniu: 09.05.2016 03:00
FaUst   12 #14 09.05.2016 07:20

@Anonim (niezalogowany): Wierz mi że niektórzy by marudzili ;)

que_pasa   9 #15 09.05.2016 08:54

@KyRol: zenity to lipa przy gtkdialog :)
http://gtkdialog.googlecode.com/svn/trunk/examples/

a tu przykład odtwarzacza muzyki w bashu z użyciem gtkdialog do tworzenia gui

http://murga-linux.com/puppy/viewtopic.php?t=31206

ogólnie da się za pomocą tego zrobić naprawdę niezłe aplikacje. System do inwentaryzacji sprzetu, oprogramowania i sieci połączony z ocsinventory w tym popełniłem kiedyś

Autor edytował komentarz w dniu: 09.05.2016 09:00
GBM MODERATOR BLOGA  20 #16 09.05.2016 09:24

@que_pasa: Dzięki za linka, warta uwagi sprawa :D

Domker   6 #17 09.05.2016 14:52

Za pomocą Linuxowego Zenity bądź Kdialog w połączeniu z bash zrobię szybciej to co trzeba niż przy pomocy takiego PowerShella.

FaUst   12 #18 09.05.2016 15:08

@Domker: A wylistujesz konta z AD, dopiszesz nowego mailboxa w Exchange'u albo zrobisz snapshot w Hyper-V? Każda powłoka ma swoje zadania.

NieGooglujMnie   6 #19 09.05.2016 15:15

Na szczęście OS X trzyma się basha, bo gdyby Apple "skumało się" tutaj z Microsoftem, to byłby bardzo mocny cios dla Linuxa.

Ludzie nie zdają sobie sprawy z tego, jak bardzo dużo daje Linuxowi dosyć wysoka kompatybilność z OS X (właśnie dzięki bashowi).

Dobrze, że Microsoft idzie w zaparte i za wszelką cenę rozwija swoje "rozwiązania". OS X (Apple) i Linux powinny trzymać się razem, to wtedy Linux będzie mocny, a Apple chociaż trochę open-source`owe :D

Autor edytował komentarz w dniu: 09.05.2016 15:20
Domker   6 #20 09.05.2016 15:22

Snapshot w Hyper-V jak najbardziej. (VirtualBox)
Active-Directory i Exchange - mówisz tu o usługach nie wpisujących się bezpośrednio w system Linux.
Jeżeli chodzi o sam system i JEGO aplikacje to można praktycznie wszystko.

mktos   10 #22 09.05.2016 18:32

Najbardziej sensowne zastosowanie GUI w PoSH to oczywiście Out-GridView, dzięki czemu mamy ładny mechanizm do przeglądania (oraz wyszukiwania, filtrowania) tabelarycznych danych poza okienkiem konsoli.

@NieGooglujMnie: To raczej odwrotnie: wielu programistów właśnie dzięki OSX ma środowisko, na którym ma programy "jak w Linuksie", ale wszystko im działa ;-)

FaUst   12 #23 10.05.2016 08:15

@TORVALDS III (niezalogowany): Dziękuję - mam "własnego" hejtera :D Miło mi ;)

KyRol   18 #24 10.05.2016 08:22

@que_pasa: A i owszem, niemniej Zenity jest tak nieprzyzwoicie łatwe i proste, że największy leń czy nawet wróg linii komend obojętnie obok niego nie przejdzie;) Tam niewiele jest do zapamiętania, a możliwości całkiem fajne. Za przykład niech posłuży skrypt do obsługi modemów GSM:

http://www.nibyblog.pl/proste-zarzadzanie-modemem-3g-w-linuxie-dzieki-onlitor-53...
http://pliki.nibyblog.pl/src/onlitor.tar.gz

Autor edytował komentarz w dniu: 10.05.2016 08:23
que_pasa   9 #25 12.05.2016 10:03

@KyRol: z takich "prostych" rzeczy od zenity wolę yad

https://sourceforge.net/projects/yad-dialog/

równie proste w użyciu jak nie prostsze

KyRol   18 #26 12.05.2016 16:50

@que_pasa: Przyznam, że Yad akurat nie znałem...

Autor edytował komentarz w dniu: 12.05.2016 16:51