Posts tagged ‘Windows’

Triki z PowerShellem #1 – GUI

2008-05-15 14:41

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:

  1. [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
  2. # Od .NET 2.0 ta metoda jest deprecated, ale tutaj nam to chwilowo nie przeszkadza ;-)

Okno komunikatu w PowerShellui 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:

  1. [System.Windows.Forms.MessageBox]::Show("Hello world!", "Message",
  2.     [Windows.Forms.MessageBoxButtons]::OK,
  3.     [Windows.Forms.MessageBoxIcon]::Information)

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:

  1. $form = New-Object System.Windows.Forms.Form
  2. $form.Text = "GUI!"
  3. [System.Windows.Forms.Application]::Run($form)

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ą.

Tags: ,
Author: Xion, posted under Applications » 2 comments

Konsolka dla okien

2008-04-14 20:59

Zasadniczo to systemy uniksowe znane są z intensywnego wykorzystania trybu tekstowego, czyli wiersza poleceń konsoli. W przypadku systemu Windows wydaje się, że jest to bardziej pozostałość po starym (nie)dobrym DOS-ie, która została prawie całkowicie zastąpiona przez interfejs graficzny. Problem jednak w tym, że nie wszystko da się zawsze wygodnie wyklikać – a co więcej, takie czynności niezbyt nadają się do zautomatyzowania (na przykład po to, aby wielokrotnie przeprowadzać zmiany w konfiguracji na wielu maszynach). Mając elastyczny tryb tekstowy, zwykle bowiem wystarczy napisać odpowiedni skrypt; w przypadku trybu graficznego nie ma takiej możliwości.
Ten mankament był w Windows obecny od dawna i różne były sposoby na jego obejście – począwszy od plików wsadowych (.bat) przez eksporty/importy Rejestru (.reg), pliki .inf czy skrypty WSH (Windows Scripting Host). Te ostatnie są na przykład znane z powodu… kilku wirusów, które zdołały się szeroko rozprzestrzenić, wykorzystując tę technologię (np. słynny I.Love.You).

Logo PowerShellWszystkie podobne pomysły rozwiązywały jednak cały problem dość średnio. Lecz od jakiegoś czasu istnieje Windows PowerShell, który wydaje się znacznie ciekawszym rozwiązaniem. Jest to tekstowa powłoka poleceń – wraz ze skryptowym językiem programowania – która nie tylko jest o wiele bardziej przydatna niż wcześniejsze wynalazki Microsoftu, ale też wypada wcale nieźle w porównaniu z innymi shellami, jak choćby bash. Ma ona bowiem kilka interesujących cech szczególnych:

  • Pozwala wykorzystać wszystkie trendy technologie windowsowe, jak COM, WMI (Windows Management Instrumentation) i przede wszystkim .NET. Większość czynności “systemowych” można wykonać, korzystając z któregoś z tych narzędzi.
  • Zamiast na tekście, w tym shellu operujemy na obiektach. Możemy je tworzyć, przekazywać jako dane wejściowe do poleceń, modyfikować, filtrować, a także dobierać się do ich składników – odczytywać właściwości i wywoływać metody. W szczególności operator przetwarzania potokowego | powoduje przekazanie między poleceniami (a dokładniej tzw. cmdletami) obiektów, a nie zwykłego tekstu.
  • PowerShell unifikuje też sposób dostępu do różnych składników systemu, jak system plików, Rejestr czy zmienne środowiskowe. Dzięki temu nie trzeba do każdego z nich stosować innych narzędzi.

W tym momencie zapewne przydałby się wymowny przykład, który może wyglądać choćby następująco:

  1. ps | where { -not $_.Responding } | kill

To polecenie najpierw listuje wszystkie procesy w systemie (ps), następnie wybiera spośród nich te, które nie odpowiadają, aby w końcu posłać je do Krainy Wiecznych Zwisów :) Operujemy tutaj na obiektach reprezentujących procesy, a jedną z ich właściwości jest, jak widać, Responding, którą można użyć do filtrowania.
W pełnej wersji komenda wyglądałaby tak naprawdę następująco:

  1. Get-Process | Where-Object -filterScript { -not $_.Responding } | Stop-Process

co być może wygląda wymowniej, lecz jest z pewnością bardziej rozwlekłe. Na szczęście PowerShell definiuje fabrycznie kilkanaście aliasów, które mapują się na polecenia odpowiadające z grubsza tym znanym z innych shelli – jak dir, ls, cd, rm, ps, man czy type. To pozwala w miarę szybko poznać podstawowe komendy i przyspiesza ich wpisywanie.

Na koniec trzeba stwierdzić, że przydatność PowerShella zależy prawdopodobnie przede wszystkim od tego, czy potrafimy wykorzystać całe to ogromne bogactwo klas .NET, COM i WMI, które powłoka ta udostępnia. Jeśli tak, to możemy znaleźć dla niej szerokie pole zastosowań. Polecam w każdym razie przyjrzenie się temu wynalazkowi (dostępnemu na każdą sensowną wersję Windows, tj. od XP SP2 wzwyż). Sam lubię używać go do zabijania procesów znacznie bardziej niż standardowego Menedżera zadań ;-)

Tags: ,
Author: Xion, posted under Applications » 3 comments

Przekierowanie standardowych strumieni

2008-03-21 10:33

Dawno, dawno temu miałem dość oryginalny pomysł na program użytkowy. Miała to być (o wiele) lepsza wersja konsoli Windows, której wyższość miała się objawiać w wyglądzie oraz możliwościach; pewne inspiracje czerpałem tutaj z terminali linuksowych oraz basha (nie, nie chodzi tu o serwis z cytatami z IRC-a ;P). Jak większość “genialnych” pomysłów, także i ten nie doczekał się realizacji. Przyczyną było to, iż nie za bardzo wówczas wiedziałem, jak można zapewnić, aby aplikacje konsolowe funkcjonowały w ramach projektowanego terminala tak, jak to robią w domyślnym oknie konsoli w Windows. Większość problemu rozbijała się o to, jak pobierać dane przez ów program produkowane i jak przekazywać do niego te wpisywane przez użytkownika.

Przekierowane standardowe wyjście
Konsolka mała i ciasna, ale własna

Jako że było to bardzo dawno temu, nie znałem wtedy jeszcze takich terminów jak ‘standardowe wejście/wyjście’, ‘proces potomny’ czy ‘pipe‘, które byłyby tutaj bardzo pomocne. Dowiedziałem się o nich więcej dopiero znacznie później, przy czym wiedza ta w większości odnosiła się do systemu zgoła innego niż Windows :)
Pomyślałem jednak, że do problemu można by wrócić – zwłaszcza, że pytanie o to, jak uruchomić program z przekierowanym wejściem i wyjściem, pojawia się stosunkowo często. Okazało się, że nie jest to specjalnie trudne i sprowadza się właściwie do trzech kroków – z których tylko pierwszy może być nieco zakręcony. Cała procedura (w Windows) może wyglądać na przykład tak:

  1. Tworzymy dwie lub trzy jednokierunkowe rury (pipe, tworzone funkcją CreatePipe), które posłużą nam do odbierania wyjścia od i dostarczania wejścia do procesu potomnego. Należy przy tym zwrócić uwagę na dwie rzeczy:
    • Kij ma dwa końce i rura też, więc trzeba uważać, aby właściwie je zidentyfikować. Jeden koniec każdego pipe‘a podamy do procesu potomnego, zaś drugi zachowamy dla siebie. Ważne jest, aby były to właściwe końce pod względem kierunku przepływu danych – i tak w przypadku przekierowywania standardowego wejścia, powinniśmy podać procesowi potomnemu uchwyt do czytania, zaś po stronie naszej aplikacji wykorzystywać uchwyt do pisania.
    • Powstałe uchwyty będziemy chcieli dziedziczyćw procesie potomnym, zaś Windows dopuszcza to tylko wtedy, kiedy wyraźnie taką chęć określimy przy tworzeniu danego uchwytu. Robi się to, wypełniając jedno pole struktury SECURITY_ATTRIBUTES (tak, tej którą w 95% przypadków się ignoruje) i przekazując ją do funkcji tworzącej pipe.
    • Oprócz standardowego wejścia (STDIN) i wyjścia (STDOUT), istnieje jeszcze standardowe wyjście błędów (STDERR), które również możemy chcieć przekierować. Stąd może być konieczny trzeci pipe, o takim samym przypisaniu końców jak ten od STDOUT.
  2. Tworzymy proces potomny (CreateProcess). Musimy mu podać właściwe końce rurek w strukturze STARTUPINFO oraz poinstruować Windows, by były one wykorzystywane (flaga STARTF_USESTDHANDLES). Ponadto musimy wskazać, że chcemy dziedziczyć uchwyty i że utworzony proces konsolowy nie powinien pokazywać okienka (CREATE_NO_WINDOW) – to już przekazujemy w parametrach CreateProcess.
  3. Obsługujemy wejście i wyjście procesu potomnego. Na to drugie (oraz na zakończenie procesu potomnego) możemy czekać przy pomocy funkcji w rodzaju WaitForMultipleObjects. Natomiast organizacja wejścia zależy już od naszej aplikacji. Warto pamiętać, że w standardowej konsoli jest ono buforowane wierszami, zatem i my powinniśmy wysyłać coś do procesu potomnego dopiero wtedy, gdy zbierzemy całą linijkę danych wejściowych.

Łatwe, prawda? ;-) W innych systemach operacyjnych robi się to minimalnie inaczej (pipe, fork, dup2, …), ale ogólna idea jest podobna. Jak widać, kilkoma małymi rurkami można zdziałać całkiem sporo :]

Tags: , , , ,
Author: Xion, posted under Programming » 1 comment

POSIX-owanie

2008-02-23 20:34

POSIX (Portable Operating System Interface) to taki śmieszny “standard dla systemów operacyjnych”, opracowany przez znane skądinąd konsorcjum IEEE. Celem jego stworzenia było zapewnienie jak największej zgodności w działaniu (lub niedziałaniu, rzecz jasna) dla aplikacji pracujących pod kontrolą różnych wariantów Uniksa. W tym celu określone jest pokaźnych rozmiarów API, które zajmować ma się takimi rzeczami jak procesy, wątki, sygnały, I/O, gniazda sieciowe, i tak dalej.
To, co POSIX w tym zakresie teoretycznie oferuje, jest w gruncie rzeczy całkiem zadowalające. Standard nie zabrania zresztą, by implementujące go systemy operacyjne dodawały do tego jakąś własną funkcjonalność.

Linuksowa maskotkaFreeBSD-owa maskotkaDlaczego więc zgodność poszczególnych systemów z POSIX-em jest w przybliżeniu odwrotnie proporcjonalna do ich popularności? :-) Wbrew pozorom te co bardziej znane, jak różnego rodzaju BSD i dystrybucje Linuksa, nie są pod tym względem doskonałe. Jedynie znacznie bardziej specyficzne Solarisy, QNX-y oraz, co ciekawe, Mac OS X spełniają standard POSIX-a w pełni.
A co z naszymi ulubionymi okienkami? W ich przypadku jesteśmy oczywiście bardzo, bardzo daleko… ale tylko do czasu. Windows można bowiem dość prosto doprowadzić do pełnej zgodności przy pomocy takich pakietów jak Microsoft Windows Services for UNIX czy Cygwin. Może to być dobra pomoc dla tych, którzy chcą pisać przenośne aplikacje bez opuszczania przyjaznego środowiska okienek.

Tags: , ,
Author: Xion, posted under Computer Science & IT » 1 comment

Z unikodem lub bez

2008-01-11 18:10

Unicode to ciekawy wynalazek. Zamiast stosować wymyślne sposoby na “przełączanie” sposobu interpretowania zwykłych 8-bitowych znaków, ktoś mądry wymyślił po prostu, że obecnie nie ma większych przeciwwskazań, aby zwykły tekst zajmował dwa razy więcej miejsca niż dotychczas. Powstał więc standard UTF-16, w którym stron kodowych nie ma, a każdy znak jest zapisany za pomocą jednego z 65536 kodów.
Ale jak to zwykle bywa z rozwiązaniami, które mają rozwiązywać istniejące problemy, Unicode natychmiast stworzył swoje własne :) Oprócz tego, że założone 16 bitów szybko okazało się za małe (stąd istnienie także UTF-32), powstał też szereg kłopotów praktycznych. Jednym z nich jest choćby to, że żyjemy w okresie przejściowym (który zresztą trwa już wybitnie długo) i że w użyciu jest zarówno unikod, jak i zwykłe ANSI. A na pierwszy rzut oka (ludzkiego i programowego) tekst jest po prostu ciągiem bajtów i bez zewnętrznych wskazówek nie jest możliwe określenie w stu procentach, czy został on zapisany w ANSI, UTF-8, UTF-16 czy UTF-32. Co więcej, znaki Unicode są oczywiście liczbami, a ponieważ zasadniczo zajmują one więcej niż jeden bajt, pojawia się problem z ustaleniem właściwej kolejności tych bajtów (little-endian lub big-endian).
Oba te problemy ma rozwiązywać tzw. znacznik porządku bajtów (Byte Order Mark), ale oczywiście jak większość dobrych praktyk, także i jego umieszczanie na początku dokumentów nie jest zbyt popularne :)

Z programistycznego punktu widzenia sprawa nie wygląda aczkolwiek aż tak źle i w większości przypadków jesteśmy w jednej z dwóch sytuacji. Pierwsza z nich to “nieświadome” korzystanie z unikodu (czy może raczej “szerokich”, dwubajtowych znaków), bo został o niego oparty używany przez nas język oraz platforma; najlepszymi przykładami są tu .NET i C# oraz Java.
Druga sytuacja to możliwość wyboru, z jakiego systemu będziemy korzystali. Bardzo dobre jest to, że prawie zawsze możemy zdecydować się na… oba, czyli potencjalne kompilowanie dwóch wersji: ANSI i Unicode. Pod Windows na przykład w programach pisanych w C++ wystarczy przestrzegać kilku prostych i dobrze znanych zasad:

  • Zamiast typów char (lub wchar_t) należy – wszędzie tam, gdzie chodzi nam o znaki – używać typu TCHAR, który w zależności od wersji zostanie zamieniony na jeden z tych dwóch.
  • Stałe napisowe należy wpisywać z użyciem makra TEXT (czyli TEXT("Coś") zamiast po prostu "Coś"), dzięki czemu zostaną one skompilowane jako łańcuchy ANSI lub Unicode.
  • Nie martwić się o to, jakich znaków używa systemowe API, bowiem wywołania funkcji systemowych zostaną przemapowane podczas kompilacji na właściwe wersje. Dotyczy to także niektórych bibliotek, jak chociażby DirectX.

Niestety, słowo ‘niektóre’ sytuuje się dość daleko od ‘wszystkie’ i dlatego ostatecznie nie jest tak różowo. Czołowe miejsce na liście “niewspółpracujących” zajmuje standardowa biblioteka C++. Z nią trzeba sobie poradzić we własnym zakresie.
Nie jest to aczkolwiek bardzo trudne, jako że każdy kompilator definiuje makro dla rozróżnienia wersji ANSI i Unicode. Visual C++ na przykład włącza w tym przypadku symbol _UNICODE, którego możemy użyć do stworzenia odpowiednich aliasów:

  1. namespace std
  2. {
  3.    #ifndef _UNICODE
  4.       // wersja ANSI
  5.       typedef string tstring;
  6.       #define cin tcin
  7.       #define cout tcout
  8.       typedef ostream tostream;
  9.       typedef istream tistream;
  10.       // ...
  11.    #else
  12.       // wersja Unicode
  13.       typedef wstring tstring;
  14.       // itd.
  15.    #endif
  16. }

Możemy je umieścić we własnym pliku nagłówkowym i dołączać we własnych projektach. Ponieważ jednak typów zależnych od znaków jest w STL całkiem sporo, można z powodzeniem użyć chociażby rozwiązania zamieszczonego na CodeProject, w razie potrzeby rozszerzając je o kolejne aliasy.

Tags: , ,
Author: Xion, posted under Programming » 2 comments

Przydatne ułatwienia dostępu

2007-12-12 23:37

Ponieważ nowoczesne systemy operacyjne – takie jak Windows – starają się być przyjazne dla wszystkich użytkowników, już od dawna wyposażone są w specjalne funkcje ułatwiające korzystanie z komputera osobom z różnymi rodzajami niepełnosprawności. Jest więc możliwość ustawienia większego kontrastu interfejsu użytkownika, włączenia śladu po kursorze, łatwiejszego wciskania skrótów klawiaturowych, i tak dalej.

Ikona Centrum ułatwień dostępu w Windows VistaChociaż większość tych możliwości zdaje się być przeznaczona wyłącznie dla wspomnianych użytkowników, to jednak przynajmniej dwie mogą być użyteczne dla wszystkich korzystających z Windows. Osobiście znam i często korzystam z dwóch takich, a mianowicie:

  • Wyświetlanie podkreśleń dla skrótów klawiaturowych w menu – takich jak np. Plik czy Wklej. Dawniej podkreślanie to było domyślnie włączone, ale ktoś pewnie kiedyś uznał, że psuje ono wygląd interfejsu i że w zasadzie nikt już klawiatury nie używa ;P Naturalnie jest to przekonanie całkowicie błędne, dlatego też uwidocznienie tychże skrótów jest bardzo dobrym pomysłem.
  • Funkcja KlawiszeMyszy. Jest to możliwość sterowania pozycją kursora myszy przy pomocy klawiszy strzałek z klawiatury numerycznej. Tym, co czyni tę funkcję przydatną, jest precyzja: jedno wciśnięcie przesunie bowiem kursor dokładnie o jeden piksel (w jednym z ośmiu kierunków), co ułatwia pracę z programami graficznymi albo rozmieszczanie elementów interfejsu użytkownika.

Jak wszystkie ułatwienia dostępu, możemy je włączyć przy pomocy odpowiedniego apletu w Panelu sterowania: Centrum ułatwień dostępu w Windows Vista lub Ułatwienia dostępu w starszych wersjach systemu.

Tags: ,
Author: Xion, posted under Applications » 1 comment

Dymki systemowego zasobnika

2007-12-10 19:09

Część paska zadań w systemie Windows obok zegara pokazującego aktualny czas to tak zwany zasobnik systemowy (system tray) lub obszar powiadomień. Tradycyjnie widnieją w nim ikonki tych aplikacji, które zasadniczo działają w tle i przez większość czasu nie wymagają interwencji użytkownika. W przeciwieństwie jednak do procesów usług, których zupełnie nie widać (o ile się nimi specjalnie nie zainteresujemy), programy te czasami wymagają naszej uwagi. I na różne sposoby mogą się starać ją zwrócić.

Możliwa jest chociażby zmiana wyglądu ikonki, polegająca na przykład na jej miganiu. Istnieje jednak wówczas ryzyko, że użytkownik tego po prostu nie zauważy – zwłaszcza, że począwszy od Windows XP ikony dłuższy czas nieaktywne są automatycznie przez system ukrywane. Poza tym zaprogramowanie migania ikony jest wbrew pozorom nieco kłopotliwe, bo całą tę animację trzeba zakodować ręcznie. A ponadto nie daje to żadnych możliwości przekazania, o co tak naprawdę naszemu programowi chodzi.
Na drugim końcu skali mieści się z kolei wyświetlenie standardowego okna komunikatu (message box). Wymaga to tylko wywołania jednej funkcji i daje gwarancję, że użytkownik nie przeoczy tej informacji. Aczkolwiek prawie pewnym skutkiem jest też podniesienie poziomu irytacji tegoż użytkownika, któremu nagle przerywamy pracę, by zasygnalizować jakąś błahostkę. Lepiej więc nie nadużywać tej metody i stosować ją do sytuacji naprawdę ważnych.

Dymek balonowyW zwykłych przypadkach bardzo dobrze natomiast sprawdza się wynalazek wprowadzony w Windows 2000, czyli tzw. dymki balonowe (balloon tips). Faktycznie wyglądają one podobnie do dymków w komiksach i pojawiają się tuż nad paskiem zadań, wskazując na ikonę, której dotyczą. Mogą przekazywać sam tekst, ale można też opatrzyć je tytułem i jedną z czterech systemowych ikon – zupełnie jak zwykłe okna komunikatu. W przeciwieństwie jednak do nich, dymki nie wyskakują znienacka i nie wymagają żadnego potwierdzania, gdyż po pewnym (ustalonym) czasie same znikają.
Niestety, niewiele aplikacji używa dymków balonowych – a szkoda, bo to jeden z ciekawszych elementów interfejsu użytkownika wprowadzonych w nowszych wersjach Windows. Prawdę mówiąc sądzę, że nawet w przypadku programów, które domyślnie “nie siedzą” w zasobniku, wykorzystanie dymków jest lepsze w przypadku zdarzeń zachodzących w tle niż np. miganie paskiem tytułowym okna. To mniej stresu i więcej informacji dla użytkownika :)

Pozostaje jeszcze kwestia programistyczna, czyli jak taki dymek wyświetlić. W Windows Forms jest to proste i wymaga na przykład wywołania metody ShowBalloonTip komponentu NotifyIcon. W klasycznym Windows API jest nieco gorzej, gdyż robimy to tę samą funkcją Shell_NotifyIcon, którą wykorzystuje się do każdej innej operacji na ikonce w trayu. Dla wygody najlepiej więc opakować ją we własną klasę.

Tags:
Author: Xion, posted under Programming » Comments Off on Dymki systemowego zasobnika
 


© 2023 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.