PowerShell - Kilka wskazówek
Sun, 29 November 2009
Wstęp
Jednym z moich ostatnich celów jest spopularyzowanie PowerShella. Dziś wiedzą o nim jedynie nieliczni, jednak Microsoft PowerShell to potężne narzędzie - to język skryptowy potężniejszy niż wszystkie inne.
Języki skryptowe dostępne są praktycznie w każdym systemie operacyjnym, pomagając administratorom, czasami ich całkowicie zastępując przy wykonywaniu żmudnych czynności - przykładowo, w tym artykule zaprezentuje dość przydatny skrypt wykonujący wsadową zmianę nazw plików.
Windows, na przestrzeni lat, posiadał kilka "swoich" (czyt. wbudowanych) języków skryptowych. Były nimi: pliki wsadowe BAT (pamiętacie?), "Host skryptów systemu Windows" (o którym praktycznie mało kto dzisiaj pamięta - jednocześnie zarzucając rodzinie Windows brak rozbudowanego języka skryptowego ;), no i wreszcie PowerShell. O ile serwer "Host skryptów systemu Windows" umożliwiał uruchamianie skryptów napisanych w już istniejących językach jak JavaScript i VisualBasic Script (odpowiednio rozszerzenia .js i .vbs), o tyle PowerShell to zupełnie nowy język, stworzony od podstaw - zgodnie z dzisiejszym nurtem myśli technicznej - całkowicie obiektowy. Obiektowość w tym przypadku przekłada się jednak na coś więcej - język posiada dostęp do składników platformy .NET (a więc metod i pól obiektów .NET).
Nie muszę chyba mówić co to znaczy? Dla osób niezorientowanych w temacie platformy .NET (która tak na marginesie powstała dlatego, że sąd zakazał Microsoft'owi tworzenia własnych, rozbudowanych implementacji języka Java firmy Sun - Microsoft stworzył więc własną, przenośną platformę .NET - czyt. "dot net" ) mogę jedynie powiedzieć - mamy łatwy dostęp do praktycznie każdego zakamarka systemu - a takie cudo jak WQL jeszcze bardziej nam to ułatwia. Co to jest WQL? Cóż - osoby znające język zapytań bazodanowych SQL powinny dostrzec analogię pomiędzy oboma akronimami. I będą miały rację. Jak dla mnie coraz większa integracja z .NET, praktycznie pełna obiektowość i WQL to jedna z większych zalet nowych Windowsów. Bo o ile oczywiście zewsząd można dzisiaj słyszeć mnóstwo narzekania na nowy system Vista, to tak naprawdę wszystko praktycznie sprowadza się do bajerów graficznych, które "podobno" wolno chodzą na starszych komputerach (to po co je włączać?), podsystemu kontroli konta użytkownika (który można wyłączyć za pomocą 5 kliknięć - Tak! Policzyłem kliknięcia!) i zużycia pamięci (Tak, to ostatnie daje rzeczywiście znać o sobie w nowszych grach, nawet przy 2GB RAMu). Niestety widać tu jakże obecną cechę człowieka do kierowania się powierzchownością podczas oceny. Osoby naprawdę znające się na rzeczy i będące przy zdrowych zmysłach (nikogo nie obrażając nie mam tu na myśli fanatycznych zwolenników konkurencyjnych systemów ;) od razu zauważą że "pod maską" sporo się zmieniło. Wbrew temu co zapowiadano (a zapowiadno, że znakomita większość systemu Vista będzie przepisana na .NET), okazało się, że system Vista jest hybrydą - czyli połączeniem systemu operującego na starym WinAPI, z systemem korzystającym z platformy .NET. Przy czym na .NET nie zostało przepisane zbyt wiele kodu - jednak wystarczająco wiele by niektóre składniki systemu zyskały nowy ład, obiektowość i możliwość dostępu przez PowerShell. Niech przykładem będzie WMI - czyli instrumentacja zarządzania systemu Windows (
http://msdn.microsoft.com/en-us/library/ms257340(VS.80).aspx). Co kryje się pod tą dziwną nazwą? Cóż, za pomocą WMI możemy odczytywać praktycznie wszystkie informacje o podłączonym sprzęcie takie jak ilość podłączonych procesorów (rdzeni również), adres MAC karty sieciowej, ale również listę uruchomionych procesów, a nawet odczyt napięcia z woltomierzy na płycie głównej (i tym podobne rzeczy - jednym słowem uzyskiwanie informacji o sprzęcie i działających usługach). Z WMI można korzystać na dwa sposoby - jednym z nich jest przebicie się przez kolejne obiekty, natomiast drugim jest właśnie WQL. WQL umożliwia nam wykonywanie zapytań - dokładnie takich jak SQL, ale kierowanych do systemowej bazy danych. I to właśnie w systemowej bazie danych przechowywane są wymienione wyżej informacje. Prawda, że przełomowe podejście? Chcesz uzyskać informacje o wspomnianym wyżej adresie MAC karty sieciowej o określonej nazwie? Nic prostszego - wystarczy jedno zapytanie WQL! Proszę bardzo:
SELECT MACAddress FROM Win32_NetworkAdapter WHERE Name LIKE '%$nazwa_karty%'
Powyższy przykład pochodzi akurat z jednego z moich skryptów.
Przykładowe skrypty
Czas na przedstawienie kilku przykładowych skryptów. Pierwszym z nich będzie...
Wsadowa zmiana rozszerzeń plików
Skrypt zmienia wsadowo wszystkie wybrane rozszerzenia w podanym katalogu na zadane.
Ważne jest, że udało mi się go napisać tak by działał w PowerShellu 1.0 (wszystkie sposoby zmiany rozszerzeń używają elementu basename, który występuje dopiero od PS 2.0).
###############################################
# #
# Wsadowa zmiana rozszerzeń plików #
# PowerShell >= 1.0 #
# #
# Autor: Łukasz "Lukas" Wyporek #
# #
###############################################
Write-Host "Wsadowa zmiana rozszerzeń plików w danym katalogu" -foregroundcolor "black" -backgroundcolor "white";
if ( ($args[0] -eq "-help") -or ($args[0] -eq "-?")
)
{
Write-Host "`n# Skrypt zmienia rozszerzenie wszystkich plików o rozszeniu zdefiniowanym w argumencie 1, znajdujących się w katalogu zdefiniowanym w argumencie 0 na roszerzenie zdefiniowane w argumencie 2.`n" -backgroundcolor "white" -foregroundcolor "black";
Write-Host "`nUżycie skryptu:";
Write-Host "`tzmien_rozszerzenie.ps1 ścieżka_do_katalogu stare_rozszerzenie_bez_kropki nowe_rozszerzenie_bez_kropki `n";
Write-Host "`nAutor: HackedByLukas `n" -foregroundcolor "gray";
exit;
}
while ($args[0] -like "")
{
$odp = (Read-Host "Podaj katalog źródłowy");
$args += $odp;
}
while ($args[1] -like "")
{
$odp = Read-Host "Podaj rozszerzenie źródłowe";
$args += $odp;
}
while ($args[2] -like "")
{
$odp = Read-Host "Podaj rozszerzenie docelowe";
$args += $odp;
}
Write-Host $args[0];
$args[1] = '.'+$args[1];
$args[2] = '.'+$args[2];
$args[0] += '\*';
$args[0] += $args[1];
$pliki = get-item $args[0];
foreach ($plik in $pliki)
{
$nowy_plik = [IO.Path]::GetFileNameWithoutExtension($plik)+$args[2];
if (($plik -like "") -or ($plik -eq ".") -or ($plik -eq "..")) { continue; }
Write-Host "Przetwarzanie " -noNewLine;
Write-Host $plik -foregroundcolor "green"
;
rename-item -path $plik -newName $nowy_plik;
}
Szybkie info o aktualnym IP, wybranego interfejsu
Szybkie info o aktualnym IP, wybranego interfejsu sieciowego:
#Clear-Host;
Write-Host "Skrypt PowerShell podający aktualny adres IP interfejsu sieciowego podanego jako parametr." -foregroundcolor "Black" -backgroundcolor "White";
Write-Host "Autor HackedByLukas `n"-foregroundcolor "Gray";
if ($args[0] -like "")
{
Write-Host "Użycie: mojeip.ps1 NAZWA_INTERFEJSU" -foregroundcolor "green";
Exit;
}
$nazwa_karty = $args[0];
Write-Host "Wyszukiwanie interfejsu sieciowego o nazwie %$nazwa_karty%";
if ($nazwa_karty -eq '')
{
$nazwa_karty = Read-Host "Proszę wprowadzić nazwę karty sieciowej:";
}
$IP=get-WMIObject -query "SELECT IPAddress FROM Win32_NetworkAdapterConfiguration WHERE Description LIKE '%$nazwa_karty%'";
Write-Host "Obecny adres IP wybranego interfejsu sieciowego to: " -noNewLine; $IP['IPAddress'];
Write-Host ""
Rozwiązania typowych problemów
Podczas pracy z PowerShellem (w wersji 1.0) przytrafiło mi się kilka niedogoności (bo tego problemami nawet nie można nazwać), które chciałbym tutaj opisać i przedstawić ich rozwiązania.
Zmiana standardowego prompta (znaku zachęty)
Krótko opiszę, jak zmienić prompt w PowerShell'u - bo to fajne jest. (Więcej przykładowych promptów znajdziecie pod poniższym adresem: http://mshforfun.blogspot.com/2006/05/perfect-prompt-for-windows-powershell.html)
- Szukamy pliku (ścieżka ilustrowana na Windows Vista):
C:\Users\NAZWA_UZYTKOWNIKA\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
(jeśli nie ma takiego katalogu ani pliku to je tworzymy) - W pliku Microsoft.PowerShell_profile.ps1 odnajdujemy funkcję prompt() i modyfikujemy ją, np w ten sposób:
(jeśli plik jest pusty to dodajemy tą funkcję do pliku)function prompt(){ Write-Host "H" -foregroundcolor "cyan" -nonewline; Write-Host "a" -foregroundcolor "magenta" -nonewline; Write-Host "c" -foregroundcolor "yellow" -nonewline; Write-Host "k" -foregroundcolor "red" -nonewline; return "> "; }
- Uruchamiamy ponownie PowerShella - powinien wystartować z nowym znakiem zachęty.
Przyspieszenie uruchamiania PowerShell'a
PowerShell w wersji 1.0 ma jedną wadę - wolno się uruchamia (tzn. o kilka sekund za długo) (w wersji 2.0 ten problem został już rozwiązany). Jest bardzo dobry sposób by to zmienić, wystarczy skompilować wszystkie jego moduły (z racji, że jest on napisany na (dot)NET'cie) do Native Image Cache.
Aby to zrobić (jeśli pierwszy raz uruchamiamy skrypty ze swojego komputera) należy zmienić politykę zabezpieczeń dotyczącą uruchamiania niepodpisanych skryptów. Robimy to w ten sposób:
set-executionpolicy RemoteSigned
^ To gwarantuje, że będziemy mogli uruchomić własnoręcznie napisane, niepodpisane skrypty, ale już nie te niepodpisane, ściągnięte z Internetu. Tutaj jest więcej o polityce zabezpieczeń (
http://www.microsoft.com/poland/technet/article/art0107_01.mspx )
Dla systemów 64-bitowych należy uruchomić taki skrypt (zapisujemy go do pliku z rozszerzeniem .ps1 ):
Set-Alias ngen @(
dir (join-path ${env:\windir} "Microsoft.NET\Framework64") ngen.exe -recurse |
sort -descending lastwritetime
)[0].fullName
[appdomain]::currentdomain.getassemblies() | %{ngen $_.location}
Dla systemów 32-bitowych należy uruchomić taki skrypt (zapisujemy go do pliku z rozszerzeniem .ps1 ):
Set-Alias ngen @(
dir (join-path ${env:\windir} "Microsoft.NET\Framework") ngen.exe -recurse |
sort -descending lastwritetime
)[0].fullName
[appdomain]::currentdomain.getassemblies() | %{ngen $_.location}
Zakończenie
Mam nadzieję, że rozjaśniłem nieco sprawę z PowerShellem, pokazałem jak bardzo jest to przełomowy język i być może udało mi się przekonać kilka osób, że jest to przyszłościowe rozwiązanie. Widzicie jak to jest - w tym artykule miałem tylko przedstawić kilka moich skryptów, a wyszło jak zwykle ;) Mam nadzieję, że skorzystaliście troszeczkę.
Na zakończenie mam mały upominek dla Was mały upominek - bardzo pomocną dla początkujących ściągawkę z PowerShella:
PowerShell - ściągawka
Użyteczne strony:
http://www.powershellpro.com/powershell-forum/ - Użyteczne skrypty posegregowane na kategorie
Źródła:
- Ściągawka z PowerShella, własne doświadczenia, dokumentacja Windows .NET ze strony MSDN
Skomentuj
Komentarze czytelników
-
- pablo
- Fri, 27 September 2013, 2:37
- Fajny wstęp do PS. Teraz by się przydało więcej szczegółów.
-
- MSM
- Thu, 6 May 2010, 15:37
- Wygląda na to że ten PowerShell się ciekawie zapowiada... A szkoda bo właśnie niedawno nauczyłem się wreszcie w miarę pisać w BAT. A teraz wszystko przepadło ;)