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 i .NET z GUI - programowanie w konsoli Windows Server

Niedawny wpis o administracji IIS z linii komend (WebAdministration - moduł PowerShell do zarządzania IIS w Windows Serv...) zahaczał o dość uniwersalny moduł konsoli PowerShell. Mimo, że wydaje się, iż jest on klasycznym językiem skryptowym, w rzeczywistości jest dużo bardziej złożony i zaawansowany! W przeciwieństwie do narzędzi z grupy wiersza poleceń, w PowerShellu możemy korzystać z obiektów .NET, WMI, czy COM. Daje to ogromne możliwości.

PowerShell w całości działa na platformie .NET, stąd można spokojnie używać klas dostępnych np. w C#. Poniżej zaprezentuję kilka poleceń pokazujących tą zależność.

Obiekty

Klasyczny przykład to dobrze znane polecenie dir (listowanie katalogu). Wykorzystajmy przetwarzanie potokowe i metodę Get-Member (listowanie właściwości i zmiennych dla obiektu):

dir | Get-Member TypeName: System.IO.FileInfo Name MemberType Definition ---- ---------- ---------- Mode CodeProperty System.String Mode{get=Mode;} AppendText Method System.IO.StreamWriter AppendText() CopyTo Method System.IO.FileInfo CopyTo(string destFileName), System.IO.FileInf... Create Method System.IO.FileStream Create() CreateObjRef Method System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType) CreateText Method System.IO.StreamWriter CreateText() Decrypt Method void Decrypt() Delete Method void Delete() (...)

Jak widać dir jest niczym innym jak obiektem typu System.IO.FileInfo. Obiekt posiada metody takie jak klasa w C#.

Zmienne

Sprawdźmy teraz co się kryje pod zmiennymi w PowerShellu.

$tmp = 45.5 $tmp | Get-Member TypeName: System.Double Name MemberType Definition ---- ---------- ---------- CompareTo Method int CompareTo(System.Object value), int CompareTo(double value), int IComparable.Co... Equals Method bool Equals(System.Object obj), bool Equals(double obj), bool IEquatable[double].Eq... GetHashCode Method int GetHashCode() GetType Method type GetType() GetTypeCode Method System.TypeCode GetTypeCode(), System.TypeCode IConvertible.GetTypeCode() ToBoolean Method bool IConvertible.ToBoolean(System.IFormatProvider provider) (...)

Zaskoczenia nie ma. Utworzona zmienna to obiekt klasy Double z .NET.

Skrypt PowerShell + .NET

A teraz mały skrypt, wykorzystujący obiekty klas prosto z .NET. Nasz mały "programik" ma następujące założenia:

  • pobieranie określonej strony www
  • zapis pobranej strony do określonego pliku (nazwa pliku posiada aktualną datę) w celu archiwizacji (dla ułatwienia analizy, pliki zapisywane są w tym samym folderze co skrypt)
  • losowanie czasu na jaki skrypt zostanie uśpiony (losowy okres, aby nie wywołać podejrzeń ;) )
  • całość działa w pętli przez pewien zadany czas

Skrypt realizujący powyższe założenia wygląda następująco (dodatkowe informacje ułatwiające zrozumienie skryptu zawarte są w komentarzach):

#na początku zapamiętujemy datę uruchomienia skryptu $start = Get-Date #zmienne (minuty) określające w jakim przedziale, losowany będzie czas uśpienia skryptu $sleepTimeMin = 10 $sleepTimeMax = 40 #jak długo ma działać skrypt (w tym przypadku 24 godziny) $howLong = 24*60 #tworzymy instancję klasy Random z .NET do losowania czasu snu $rand = New-Object System.Random do{ $now = Get-Date #tworzymy obiekt WebClient z .NET do pobiernia danych z www $wc = New-Object System.Net.WebClient Write-Host "zaczyna pracę" #pobranie strony www $data = $wc.DownloadString("http://www.dobreprogramy.pl/djfoxer") #zapis pobranych danych do pliku, który w nazwie zawiera aktualną datę $data >> "downloaded $($now.ToString().Replace(':','.')).html" #losowanie czasu uśpienia $sleepTime = $rand.Next($sleepTimeMin, $sleepTimeMax) #uśpienie skryptu (domyślnie parametrem wejściowym Start-Sleep są sekundy) Write-Host "zasypiam na $($sleepTime) minut..." Start-Sleep ($sleepTime * 60) Write-Host "budzenie!" #sprawdzenie, czy wybudzony skrypt nie powinien już zakończyć działanie }while(($now - $start).TotalMinutes -lt $howLong) Write-Host "koniec"

Przykładowy skrypt pokazał jak można polecenia PowerShella połączyć z obiektami prosto z .NET. Dzięki temu, w prosty i szybki sposób można stworzyć wydajne skrypty, które mają olbrzymie możliwości. Znajomość tego typu zależności z .NET dla zaawansowanego administratora, może okazać się zbawienna i nieraz pozwoli zaoszczędzić czas i ułatwi pracę w środowisku serwerowym.

GUI

Skoro PowerShell to .NET, więc można spróbować stworzyć w nim GUI używając obiektów z frameworku. Do wyboru mamy WinForms lub WPF. Skupię się głównie na tej pierwszej opcji. Skrypt z WinForms wygląda podobnie, wręcz identycznie, jak plik designer generowane np. przez Visual Studio.

Przedstawię teraz mały skrypt, który korzysta z GUI pod PowerShellem. Jego zadaniem będzie listowanie za pomocą polecenia dir zawartości folderu. Ścieżkę do katalogu nie będziemy podawali w konsoli, ale w polu tekstowym w oknie graficznym aplikacji PowerShell. Uruchomienie polecenia nastąpi po naciśnięciu odpoweidniego przycisku. Zawartość zostanie przedstawiona w kontrolce listbox. Ostatnim elementem na formatce jest przycisk do zamknięcia okna.

Kod z komentarzami omawiającymi poszczególne elementy skryptu, przedstawia się następująco:

#tworzymy instancję okna $form = New-Object System.Windows.Forms.Form #okno otrzymuje nazwę, rozmiar oraz pozycję (środek ekranu) #podobne właściwości otrzymują pozostałe obiekty wrzucane na okno $form.Text = "PowerShell GUI Test" $form.Size = New-Object System.Drawing.Size(500,520) $form.StartPosition = "CenterScreen" #dodajemy listę, na której będą wyśwetlać się elementy $listBox = New-Object System.Windows.Forms.Listbox $listBox.Location = New-Object System.Drawing.Size(5,50) $listBox.Size = New-Object System.Drawing.Size(470,400) $form.Controls.Add($listBox) #dodajemy przyciski do zamknięcia okna $close = New-Object System.Windows.Forms.Button $close.Location = New-Object System.Drawing.Size(0,450) $close.Size = New-Object System.Drawing.Size(100,30) $close.add_click({$form.Close()}) $close.Text = "Zamknij" $form.Controls.Add($close) #dodajemy pole tekstowe, gdzie wpisywać będziemy adres ścieżki $textBox = New-Object System.Windows.Forms.TextBox $textBox.Location = New-Object System.Drawing.Size(5,10) $textBox.Size = New-Object System.Drawing.Size(470,100) $form.Controls.Add($textBox) #przycisk, który wykonuje komendę dir #ścieżka dla polecenia brana jest z pola tekstowego textBox $dir = New-Object System.Windows.Forms.Button $dir.Location = New-Object System.Drawing.Size(120,450) $dir.Size = New-Object System.Drawing.Size(100,30) $dir.add_click({ #po wciśnieciu przycisku "DIR" czyścimy listę $listBox.Items.Clear() #listujemy elementy w folderze podanym w polu tekstowym $values = dir -Path $textBox.Text #wrzucamy elementy na listę foreach ($item in $values){ $listBox.Items.Add($item.Name) } }) $dir.Text = "DIR" $form.Controls.Add($dir) $form.ShowDialog()

Kilkoma poleceniami w PowerShell stworzyliśmy proste środowisko GUI dla administratora. Idealne jeśli pewne skrypty mają być obsługiwane przez osoby, które nie muszą mieć dużej wiedzy w PowerShellu, czy znać wszystkie składniki metod. Co więcej, w takiej sytuacji można wykluczyć część błędów i zmniejszyć ryzyko nieodpowiedniego użycia poleceń.

Oczywiście na początku tworzenie GUI pod PowerShella wydaj się lekko skomplikowane. Na szczęście powstało kilka narzędzi, ułatwiających tworzenie graficznych interfejsów do PowerShella. Dzięki edytorom typu WYSIWYG (ang. What You See Is What You Get) wyklikanie GUI nie powinno nastarczyć problemów. Listę narzędzi można znaleźć pod adresem: PowerShell GUIs.

Podsumowanie

Znajomość .NET dla zaawansowanych administratorów wydaje się rzeczą bardzo atrakcyjną. Nie tylko zwiększa szybkość i komfort pracy, dzięki skryptom o większych możliwościach, ale także pozwala na proste tworzenie własnych skryptów z GUI. Bardziej przyjazny interfejs idealnie nada się dla mniej doświadczonych osób, które muszą skorzystać ze skryptów i przy okazji pełnić może formę walidatora. Warto znać wszystkie możliwości PowerShella, aby móc pracować efektywniej, szybciej i prościej. 

porady programowanie serwery

Komentarze

0 nowych
okokok   12 #1 28.01.2013 19:37

ooo okienko :)
nie wpadł bym na to że można w ps pisać gui

Autor edytował komentarz.
alucosoftware   7 #2 28.01.2013 20:42

Bardzo miło się czytało. Świetny wpis.

"Oczywiście na początku tworzenie GUI pod PowerShella wydaje się lekko skomplikowane."

Ależ proszę ;) Bardzo rzadko korzystam z graficznego designera w VS i uważam, że to tylko usprawniło moją pracę. Poszczególne elementy GUI nie stanowią wtedy "czarnych skrzynek", a i zależności między nimi dają się lepiej zaobserwować.

tfl   8 #3 28.01.2013 21:20

Uwielbiam tego typu Twoje wpisy. Kaganek oswiaty dla bashujacych.

mktos   9 #4 28.01.2013 21:34

@alucosoftware: Z tego powodu między innymi fajny jest WPF/Silverlight, gdzie pisanie kontrolek w kodzie jest naturalne.

iluzion   5 #5 28.01.2013 22:06

Bardzo dobrze napisane.

Ps Mój pierwszy (i jedyny jak dotąd) kontakt z PowerShell zakończył się na próbie uruchomienia pliku bat, który działa w CMD.

https://dl.dropbox.com/u/1010315/misc/ps.png

wojtekadams   18 #6 28.01.2013 23:30

Znów wyczarowałeś niezły wpis ;)

kaluzaaa   5 #7 29.01.2013 00:32

Co do gui to w ps najlepiej moim zdaniem sprawdza się moduł ShowUI z codeplex.

djfoxer   17 #8 29.01.2013 13:08

Dzięki :) Tworzenie tego wpisu było naprawdę przyjemne, cieszę się, że dobrze to wyszło.

@okokok
To powiem Ci jeszcze, że można GUI do skryptów pisać w HTML :)

@alucosoftware
To fakt. Ja częściej tworzę w ASP i w sumie nawet nie pamiętam kiedy bym korzystał z designera. W sumie jeszcze do aplikacji okienkowych designer, nawet jak sam piszesz, czasem jest używany. Ale tworzenie aplikacji w ASP w designerze to już jest "sztuka" :P

@iluzion
Ale ten błąd, który podałeś wynika tylko z tego, iż zablokowane jest uruchamianie skryptów. Wystarczy wpisać w PS: Set-ExecutionPolicy RemoteSigned

@kaluzaaa
Też tak myślę, miła składania i cały czas mamy kontrolę nad kodem. Sporo osób zaś chwali PowerShell Studio, jeśli chodzi o edytory graficzne.

  #9 29.01.2013 17:56

mamy gdzieś jakiegoś geeka linuxowego który pokaże jak obsłużyć gui z poziomu basha ?

alucosoftware   7 #10 29.01.2013 21:31

@_asd
Nie jestem może zagorzałym zwolennikiem Linuksa, ale nie trzeba być ani geekiem ani omnibusem, aby wiedzieć, że Tcl/Tk datowany jest na "ciut" wcześniej niż microsoftowy PowerShell, więc daruj sobie uszczypliwości.

Autor edytował komentarz.
  #11 29.01.2013 22:14

Nie musze sobie ani komus niczego darowac,bo zapewne znajdzie sie ktos kto z basha stworzy np. skrypt pythona z pyQt

iluzion   5 #12 03.02.2013 22:53

@_asd

"z basha stworzy np. skrypt pythona z pyQt"

To basha czy pythona? ;) Ten sam skrypt py będzie działał również pod Windows. Poniżej screen podobnego programu:

https://dl.dropbox.com/u/1010315/blog_dp/QDirModel.png

Kod źródłowy: http://dpaste.com/hold/906698/