Pisząc skrypty w PowerShellu mamy dostęp do niemal całej platformy .NET, zawierającej grubo ponad dziesięć tysięcy klas, dlatego nieczęsto będziemy potrzebowali czegoś spoza tego wielkiego bogactwa. Ale takie przypadki też istnieją. Na szczęście PSh umożliwia też dostęp do innych narzędzi niż .NET – jak choćby do starych (nie)dobrych obiektów COM.
Przy ich pomocy można zrobić całkiem sporo, zwłaszcza jeśli chodzi o sterowanie aplikacjami, które udostępniają na zewnątrz odpowiednie interfejsy (a robi tak wiele większych programów, nie tylko Microsoftu). Ciekawsze jest chyba jednak łączenie technologii: “starego” COM-a i nowego .NET-a, aby razem zrobić coś użytecznego. Oto prosty przykład:
Dziwnym trafem najprostsze przykłady użycia COM są zwykle związane z tworzeniem skrótów (plików .lnk) przy pomocy metody CreateShortcut
obiektu COM o identyfikatorze WScript.Shell
. Obiekt ten był dawniej używany w skryptach hosta systemu Windows (Windows Scripting Host) i, jak widać, nadal zdarza mu się być użytecznym ;-)
Co jednak robi powyższy skrypt? Otóż nie tworzy żadnych nowych skrótów, a wręcz przeciwnie: wskazuje kandydatów do usunięcia, czyli skróty pokazujące na nieistniejące pliki lub katalogi. Na wyjściu dostajemy ich zgrabną listę, którą możemy przekierować na przykład do polecenia Remove-Item
.
A tak możemy sobie wyczyścić Menu Start:
I pomyśleć, że kiedyś napisałem do tego cały osobny program… :)
Preprocesor w C++ to może i przestarzała, ale i całkiem fajna zabawka. Przynajmniej czasami – mimo dość ubogiej logiki – pozwala ona załatać choć niektóre braki języka. A niekiedy pozwala też na pewne sztuczki, jakie ciężko byłoby osiągnąć inaczej. W końcu, można go też używać do tego, w czym jest najlepszy: do automatycznego wklejania powtarzających się fragmentów kodu w wielu miejscach.
Ponieważ jednak preprocesor działa na kodzie jak na tekście, to rezultaty mogą być czasami zadziwiające – zwłaszcza dla kompilatora. Może on nam wówczas pokazać błąd w linijce, która jest całkowicie poprawna… Ale tylko z dokładnością do zawartego w niej makra, które po rozwinięciu generuje błąd składniowy lub semantyczny. Weźmy chociażby chyba najprostszy przypadek tego typu:
W nim łatwo o wykrycie pomyłki, lecz w rzeczywistych sytuacjach może to być zadanie nie lada. Zwłaszcza wtedy, gdy użyte makro jest skomplikowane, a my przecież nie możemy przełączyć preprocesor w tryb pracy krokowej i śledzić, jak jest ono rozwijane.
Możemy jednak przynajmniej podejrzeć ostateczne rezultaty. Wprawdzie domyślne każdy plik źródłowy po przetworzeniu przez preprocesor trafia od razu do kompilatora, jednak zachowanie to można łatwo zmienić. Możliwe jest na przykład zrzucenie wstępnie przetworzonego źródła do pliku, który to możemy potem przejrzeć i zobaczyć, w co ostatecznie nasze makra się zmieniły.
W Visual C++ takie zachowanie ustawia się we właściwościach projektu, na zakładce Configuration Properties > C/C++ > Preprocessor. Tam możemy wybrać, czy chcemy, by rezultaty działania preprocesora na plikach .cpp były zapisywane do osobnych plików (z rozszerzeniem .i). Wachlarz opcji umożliwia też określenie, czy mają być do nich dołączane numery linii lub komentarze.
Włączenie tych opcji bywa przydatne, jeśli dostajemy na linijkach kodu z użyciem makr dostajemy komunikaty o błędach kompilatora, które są zupełnie “z innej bajki”. Ponadto w ten sposób można też zobaczyć, jakie fragmenty kodu są kierowane do kompilacji za pomocą dyrektyw typu #ifdef
, co też bywa przydatne.
Pamiętajmy jednak, że wygenerowane w ten sposób pliki .i są prawie zawsze bardzo, bardzo duże – rzędu kilku megabajtów – gdyż zawierają treść wszystkich dołączonych nagłówków. Dlatego, ze względu na szybkość budowania projektu, nie powinniśmy ich generować poza przypadkami debugowania preprocesora.
Parę dni temu odbyła się premiera nowej wersji przeglądarki Opera, oznaczonej numerkiem 9.5. Z kolei jutro z wielką pompą opublikowana zostanie trzecia edycja Firefoksa. Przy tej zresztą okazji Mozilla organizuje Dzień Pobierania, z zamiarem ustanowienia rekordu ilości ściągnięć oprogramowania w ciągu jednej doby. (Mam aczkolwiek przeczucie, że prawdopodobne jest ustanowienie innego rekordu: najdłużej niedziałającego serwera pobierania ;]).
Zbieżność tych dwóch wydarzeń zapewne nie jest przypadkowa. Tym bardziej dziwi mnie to, że przy tej okazji zaprzysięgli fani któregoś z tych dwóch programów zajmują się głównie wykazywaniem w każdym możliwym miejscu, iż to właśnie ich ulubiona przeglądarka jest lepsza od tej drugiej. Naturalnie, argumentów jest przy tym mnóstwo: a to gesty myszki, a to współdzielenie zakładek i Ulubionych między komputerami, nie wspominając o tysiącach dostępnych rozszerzeń i wtyczek, coraz lepszych wynikach testów typu Acid3, wbudowanych klientach innych usług niż WWW, kilogramach skórek i pewnie wielu jeszcze innych zaletach. Część z nich może i jest ważna i interesująca. Rzecz w tym, że – statystycznie rzecz biorąc – nie obchodzą one psa z kulawą nogą.
Smutna prawda jest taka, że nadal większość użytkowników Internetu korzysta z “jedynie słusznej” przeglądarki pewnej znanej skądinąd firmy, a o dywagacjach na temat wyższości innych nad jeszcze innymi nigdy tak naprawdę nie słyszeli i raczej nie mają zamiaru usłyszeć. A to z wielu powodów niepokojące, chociażby ze względu na bezpieczeństwo czy powszechność stosowania standardów sieciowych. Wzajemne zwalczanie się zwolenników przeglądarek “niezależnych” (że je tak umownie nazwę…) na pewno nie zaradzi temu, iż połowa internautów wciąż używa do przeglądania Sieci programów przestarzałych i dziurawych jak ser szwajcarski.
A bliskość premier nowych edycji dwóch bezpiecznych, wygodnych i nowoczesnych przeglądarek to przecież całkiem dobra okazja, żeby coś na to poradzić. Zamiast więc bezowocnie spierać się, czy Safari jest lepsze od Opery, a ta od Firefoksa czy Camino, można by wspólnie zwiększyć wysiłki na rzecz uświadamiania użytkownikom niesłusznie najpopularniejszych przeglądarek, że istnieją dla nich o wiele lepsze alternatywy. Cóż bowiem z tego, że oto “wszyscy” przerzucą się czy na to Firefoksa, Operę czy inny tego typu program, jeśli ci ‘wszyscy’ to tak naprawdę ledwie 1/3 internautów?…
Jakiś czas temu pokazałem, że w PowerShellu można zrobić rzeczy, które są – jak na konsolkę tekstową – co najmniej niespotykane. Przedstawiłem na przykład sposób na wyświetlenie zwykłego windowsowego okienka. Nie było ono aczkolwiek zbyt interesujące, jako że w środku było zupełnie puste – chociaż, oczywiście, Aero robił co mógł, by wyglądało ono na atrakcyjniejsze niż było w rzeczywistości ;)
Jako że zajmowania się rzeczami zupełnie nieprzydatnymi nigdy dość, postanowiłem więc pewnego razu spróbować wnieść w stworzoną formę nieco więcej życia. Efekty okazały się raczej ciekawe, przedstawiając się następująco:
Tak, to jest trójkąt. Tak, on się obraca. Tak, na pasku tytułowym okna jest napisane Direct3D… Wszystkie te trzy fakty nie są żadnym zbiegiem okoliczności :) Za wszystko odpowiedzialny jest ten ono skrypt:
Przyznam, że byłem mocno zaskoczony, iż taki trik jest w ogóle możliwy przy pomocy czegoś, co w założeniu jest tylko powłoką tekstową dla poleceń administracyjnych. A tu proszę: DirectX w całej (aczkolwiek zarządzanej) okazałości!
Nietrudno rzecz jasna zauważyć, że powyższy skrypt jest w dużym stopniu tłumaczeniem na język PowerShella odpowiedniego kodu, który mógłby zostać napisany w dowolnym języku programowania z platformy .NET. Trzeba było jedynie poradzić sobie z pewnymi niedogodnościami, jak na przykład koniecznością ręcznego załadowania assemblies czy jakimś obejściem braku sensownej możliwości reakcji na zdarzenia – tutaj “program” po prostu kończy się po 5 sekundach.
Właśnie ta niemożność sprawia, że tandem PowerShell + DirectX zapewne nie ma przed sobą świetlanej przyszłości w grach :) Przez chwilę zastanawiałem się, czy wobec tego nie da się go użyć do tworzenia dem… Niestety, już powyższy skrypt zajmuje ponad 2 kilobajty, nie potrafiąc przy tym zbyt wiele, więc ta możliwość też prawdopodobnie odpada.
Pozostaje zatem pokazywanie podobnych trików linuksowcom i wytykanie im, że ich bash czegoś takiego nie potrafi ;D
W Windows większość czynności administracyjnych można wykonać przy pomocy interfejsu graficznego. Wraz z wprowadzeniem PowerShella częściowo się to zmieniło, bo – jak to już kilka razy pokazywałem – stanowi on bardzo ciekawą tekstową alternatywę. Istnieje jednak narzędzie, które zamyka to kółeczko i powraca do interfejsu graficznego – to PowerGUI.
Pomysł wydawać się może dziwny, bo przecież GUI nigdy nie osiągnie tego, co jest największą zaletą dobrej konsolki i powłoki tekstowej – ogromnej elastyczności. PowerGUI radzi sobie jednak całkiem nieźle, oferując spore możliwości dostosowywania tego, jakie informacje chcemy przeglądać i jakie dodatkowe akcje możemy na nich wykonać. Obie te rzeczy koduje się po prostu za pomocą poleceń PowerShella; mamy tu elementy zwane script nodes, które wyświetlane są w formie drzewka i po wybraniu prezentują rezultaty jakiejś komendy, np. listę wszystkich uruchomionych procesów (
Get-Process
). Dodatkowo możemy przypisać im też akcje wykonywane na zwróconych elementach lub odwołania do innych kolekcji obiektów (np. usług zależnych od danej).
Ogólnie pomysł wydaje się całkiem zgrabny i ma potencjał oszczędzania czasu – zwłaszcza że klepanie dość rozwlekłych komend PowerShella może być raczej męczące.
Według mnie znacznie przydatniejszą częścią PowerGUI jest dołączony edytor skryptów. To nic innego, jak (niemal) pełnowartościowe IDE do skryptów .ps1. Oprócz kolorowania składni oferuje ono debugowanie przy pomocy pracy krokowej i breakpointów oraz podglądanie wartości zmiennych – czyli prawie wszystko, co programiście do szczęścia potrzebne :)
I właśnie ten edytor jest, jak sądzę, najważniejszych powodem, dla którego powinniśmy rzucić okiem na PowerGUI, jeśli przynajmniej od czasu do czasu używamy PowerShella. Nie od rzeczy jest też argument, że cały ten pakiet licencjonowany jest jako freeware, więc możemy go używać bez ograniczeń do dowolnych celów. Zanim więc druga wersja PowerShella (która ma oferować między innymi środowisko graficzne) wyjdzie w świat, jest to całkiem rozsądna propozycja.
Oto zadanie: mamy plik, który chcemy komuś przesłać przez Internet i mieć przy tym jak najmniej zawracania głowy. Jest oczywiście e-mail, są komunikatory, podprotokół IRC-a o nazwie DCC serwisy typu RapidShare, itd. Każdy z tych sposobów wymaga jednak albo wymiany jakichś informacji typu adres czy numer identyfikacyjny, albo nie zawsze chce działać w różnych konfiguracjach sieci (zwłaszcza gdy jedna ze stron jest ukryta za NAT-em), albo… wymaga wpatrywania się w literki celem odróżnienia psów od kotów :)
Jeśli jednak dysponujemy serwerem FTP z zawartością dostępną przez HTTP (czyli po prostu hostingiem strony WWW), to możemy dzielić się plikami w prostszy i szybszy sposób. W tym celu posłużyć się można odpowiednim skryptem w PowerShellu, który potrafi samodzielnie połączyć się z serwerem FTP i wgrać na niego podany plik, a potem zwrócić jego URL. Następnie możemy przekazać go osobie, której chcemy przekazać plik.
Całkiem zmyślnie, prawda? Wystarczy jedynie odczytać lokalny plik, a następnie użyć .NET-owej klasy System.Net.FtpWebRequest
w celu wykonania “żądania FTP” w postaci uploadu tegoż pliku na serwer.
Co jednak zrobić z takim skryptem, aby był użyteczny?… Jako że jego parametrem jest ścieżka do lokalnego pliku, który chcemy załadować, możemy użyć następującej komendy:
w celu jego wywołania – o ile potrafimy sprawić, by system Windows zamienił nam symbol zastępczy %1
na rzeczoną ścieżkę. Jest to możliwe przynajmniej na dwa sposoby:
SendTo
, zawierający powyższą komendę, i nazwać go odpowiednio intuicyjnie. Po odświeżeniu Eksploratora, we wspomnianym menu pojawi się nowa pozycja, której wybór uruchomi nam nasz skrypt dla wybranego pliku.HKEY_CLASSES_ROOT/*/shell
. Tworzymy tam nowy podklucz, nazywając go jakoś odpowiednio (np. upload
) i wpisując jako wartość domyślną tekst polecenia, który chcemy zobaczyć w menu (np. Upload). Następnie tworzymy tam podklucz command
, ustawiając jego wartość domyślną na polecenia uruchomienia skryptu. Odświeżamy Eksplorator i mamy już nowe polecenie w menu kontekstowym.Sprytne i wygodne. I kto teraz powie, że tylko w systemach linuksowych można bezustannie kombinować, by dostosowywać je do swoich potrzeb ;-)
PS. Użyty w skrypcie program clip jest bardzo prosty: kopiuje on po prostu swoje wejście do Schowka. Niestety, to malutkie narzędzie nie jest obecne w Windows XP. Nie ma tam więc prostego sposobu na wpisanie tekstu do Schowka z poziomu PowerShella. Alternatywą jest wypisanie URLa- do załadowanego pliku bezpośrednio w oknie konsoli PSh. Wystarczy po prostu zmienić clip
na Out-Host
, a także zmienić wywołanie skryptu, dodając parametr -NoExit
:
To sprawi, że o wykonaniu operacji konsola PowerShella pozostanie otwarta wraz z wypisanym w niej URL-em, który można z niej skopiować.
Windows PowerShell jest oczywiście powłoką tekstową z wierszem poleceń. Wszystkie więc czynności, jakie możemy w nim wykonać, wiążą się z wpisywaniem tychże poleceń i odczytywaniem wyników, podawanych także w postaci tekstowej. Prosto, minimalistycznie i naturalnie.
I właśnie dlatego jednym z pierwszym eksperymentów, jakie przy użyciu tego narzędzia wykonałem, była… próba wyświetlenia okienka z GUI :) Najpierw miało to być skromne okienko komunikatu (message box), jednak szybko okazało, że nie będzie to wcale łatwe. Domyślnie w PowerShellu nie jest bowiem załadowane assembly System.Windows.Forms
, które to jest niezbędnie potrzebne do zabawy z okienkami. Nie oznacza to na szczęście, że oprócz jego załadowania należy też korzystać z niewygodnego interfejsu refleksji, aby cokolwiek przy jego użyciu zrobić (np. stworzyć obiekt klasy i wywołać jego metodę). Wystarczy po prostu jedno wywołanie w stylu:
i od tej pory można już zupełnie normalnie korzystać z Windows.Forms… No, prawie. Możemy w każdym razie uraczyć się okienkiem komunikatu:
A gdy już na nie popatrzymy, to pewnie zechcemy też czegoś więcej – na przykład “prawdziwego” okna, czyli zwykłej formy. To także jest do zrobienia:
Bez większego problemu można by zresztą dodać do formy kontrolki potomne, jak przyciski czy pola tekstowe… Jest jednak jeden poważny problem: właściwie nie ma sposobu na podpięcie pod nasze kontrolki procedur zdarzeniowych – nawet mimo tego, że przy użyciu wyjątkowo perfidnej sztuczki da się w PowerShellu tworzyć delegaty. Stworzone okienka pozostaną więc na wpółmartwe i specjalną funkcjonalnością nas nie zaskoczą.