Skryptowanie Windowsa: WSH

tech • 962 słowa • 5 minut czytania

Ta notatka została oznaczona jako wymagająca dopracowania: mal-repo-code.
Zawartość wpisu może ulec zmianie, zatem zapraszam do ponownych odwiedzin w niedalekiej przyszłości :)

Kolejny wpis z serii “Windows też da się łatwo oskryptować”. Poprzednia notka dotyczyła prostych skryptów wiersza poleceń, a teraz przyszła pora na skryptowanie z wykorzystaniem WSH.

WSH, czyli Windows Script Host jest mechanizmem umożliwiającym skryptowanie systemu Windows w dużo większym stopniu i ze znacznie większymi możliwościami, niż proste skrypty powłoki. Host skryptów jest domyślnie instalowany wraz z systemem (od Windows 98) z dwoma standardowymi interpreterami VBScript oraz JScript. Po doinstalowaniu odpowiednich bibliotek można również używać Perla, Pythona, czy jakiegokolwiek innego języka. Zawdzięcza się to oparciu całego mechanizmu na wykorzystanie obiektów COM/DCOM. Za pomocą WSH można zrobić prawie wszystko w systemie, więc idealnie nadaje się do wykorzystania w bardziej złożonych skryptach niż sam wiersz poleceń.

Standardowo, aby się nie powtarzać odsyłam do MSDN-a, gdzie można znaleźć dużo niezbędnych informacji o hoście skryptów w dedykowanym mu dziale - Windows Script Host. Tytułem wstępu mogę powiedzieć jedynie tyle, że Windows Scripting Host bazuje na obiektowym modelu udostępniając szereg obiektów, z których można korzystać w celu uzyskania dostępu do różnych komponentów powłoki i systemu Windows.

Jądrem hosta jest obiekt o nazwie WScript, który zawsze istnieje i jest dostępny przynajmniej w jednym egzemplarzu. Za jego pomocą możemy uzyskać informacje o samym hoście oraz o wykonywanym skrypcie. Obiekt ten tworzy również wszelkie inne obiekty jakie chcemy wykorzystać w naszym skrypcie - metoda CreateObject. Bezpośrednio w modelu obiektowym WSH można utworzyć tylko dwa obiekty: WshShell oraz WshNetwork. Wszystko inne uzyskuje się poprzez wywołanie metod tych obiektów.

Istnieją dwie wersje hosta skryptów WSH: WScript i CScript. Wersje te różnią się tylko trybem działania, a dokładnie standardowym strumieniem wyjścia. WScript działa w trybie graficznym, dane z standardowego wyjścia prezentowane są w formie graficznej za pomocą MessageBox-a, natomiast CScript wyświetla komunikaty w wierszu polecenia - konsoli.

Obie wersje interpretują skrypty w postaci pliku tekstowego, wykonując zawarte w nim polecenia. Wybór parsera dokonywany jest na podstawie rozszerzenia pliku skryptu, ale za pomocą przełącznika /E można ręcznie wybrać silnik w jakim zostanie uruchomiony skrypt.

Jako prosty przykład skryptu niech posłuży zaimplementowany przeze mnie odpowiednik uniksowej aplikacji uptime, pokazującej nieprzerywany czas pracy systemu. Wykorzystałem VBS-a:

Option Explicit

Const strComputer = "."

Dim objWMIService, objOS
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
For Each objOS In objWMIService.InstancesOf("Win32_OperatingSystem")
	Dim objSWbemDateTime
	Set objSWbemDateTime = CreateObject("WbemScripting.SWbemDateTime")
	objSWbemDateTime.Value = objOS.LastBootUpTime

	Dim seconds, hours, minutes, days
	seconds = DateDiff("s", objSWbemDateTime.GetVarDate, Now)
	days = Fix(seconds / 86400)
	seconds = seconds - (days * 86400)
	hours = Fix(seconds / 3600)
	seconds = seconds - (hours * 3600)
	minutes = Fix(seconds / 60)
	seconds = seconds - (minutes * 60)

	Dim strUptime
	strUptime = hours & ":" & minutes & ":" & seconds
	if (days = 1) then
		strUptime = days & " day, " & strUptime
	elseif (days > 0) then
		strUptime = days & " days, " & strUptime
	end if

	WScript.Echo "Uptime: " & strUptime
next

Dla JScript-a ogólny schemat byłby taki sam, a jedyną widoczną różnicą byłyby specyficzne właściwości i cechy języka…

Ten prosty skrypt można wzbogacić o obsługę argumentów i za jego pomocą sprawdzać uptime zdalnego systemu, wystarczy modyfikować zawartość stałej strComputer definiującej nazwę hosta komputera.

Jak widać VBS i JS bardzo dobrze nadają się do tworzenia prostych narzędzi systemowych związanych z obsługą samego systemu, bądź jego nadzorowania, czy też pobierania informacji o jego stanie.

Do łatwego używania, takich skryptów i narzędzi spod wiersza poleceń, warto zarejestrować w systemie dodatkowy typ plików np. vbs_console i js_console, który domyślnie będzie uruchamiał skrypty o takim rozszerzeniu w trybie wiersza poleceń. Można to wykonać w łatwy sposób wprost z konsoli za pomocą polecenia assoc i ftype, jak przedstawiono na stronie How to directly call console-mode VBScript programs from the command-line.

Taka mała dygresja. Czemu w Viście usunięto łatwy i prosty sposób na modyfikowanie powiązań plików i menu kontekstowego w opcjach folderów/plików. Teraz musimy męczyć się z ręczną edycją rejestru, bo wspomniane polecenia assoc i ftype tylko ustawiają akcję dla komendy open.

Lepszym i szybszym sposobem może być skopiowanie gałęzi dla JS i VBS wraz z małymi modyfikacjami w celu zachowania dodatkowych pozycji w menu kontekstowym do edycji, drukowania. Wystarczy zaimportować poniższy fragment rejestru, zmieniając ścieżkę do swojego ulubionego edytora:

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\.vbs_console]
@="VBSConsoleFile"

[HKEY_CLASSES_ROOT\VBSConsoleFile]
@="VBScript Console File"

[HKEY_CLASSES_ROOT\VBSConsoleFile\DefaultIcon]
@="C:\\Windows\\System32\\WScript.exe,3"

[HKEY_CLASSES_ROOT\VBSConsoleFile\Shell]
@="Open"

[HKEY_CLASSES_ROOT\VBSConsoleFile\Shell\Edit]

[HKEY_CLASSES_ROOT\VBSConsoleFile\Shell\Edit\Command]
@="C:\\Program Files (x86)\\PSPad editor\\PSPad.exe \"%1\""

[HKEY_CLASSES_ROOT\VBSConsoleFile\Shell\Open]

[HKEY_CLASSES_ROOT\VBSConsoleFile\Shell\Open\Command]
@="C:\\Windows\\System32\\CScript.exe /E:vbscript /Nologo \"%1\" %*"

[HKEY_CLASSES_ROOT\VBSConsoleFile\Shell\Open2]
@="Open &with Explorer"

[HKEY_CLASSES_ROOT\VBSConsoleFile\Shell\Open2\Command]
@="C:\\Windows\\System32\\WScript.exe /E:vbscript \"%1\" %*"

[HKEY_CLASSES_ROOT\VBSConsoleFile\Shell\Print]

[HKEY_CLASSES_ROOT\VBSConsoleFile\Shell\Print\Command]
@="C:\\Windows\\System32\\Notepad.exe /p %1"

Analogicznie przeprowadzając operację to dla JS-a. A dodanie do zmiennej środowiskowej pathext nowych rozszerzeń .vbs_console;.js_console pozwoli bez problemu uruchamiać skrypty w konsoli bez podawania ich rozszerzenia.

Ciekawostką jest możliwość tworzenia skryptów-modułów w kilku różnych językach. Służą do tego pliki XML o rozszerzeniu wsf. Dzięki temu nie trzeba się ograniczać do jednego pliku i języka w danym skrypcie.

Na koniec pojawia się pytanie - w czym pisać skrypty pod WHS - VBScript czy JScript?

Na to pytanie można szukać odpowiedzi nawet na MSDNie - Clinick’s Clinic on Scripting #1: VBScript or JScript?. Ja osobiscie bym wybrał JScript-a, bo to prawie czysty JavaScript i składnia podobna do języków C-podobnych. VBScript jest za to polecany dla programistów Visual Basica. Inną sprawą jest fakt, że VBScript pomału umiera śmiercią naturalną. Mimo, iż to właśnie w nim można znaleźć najwięcej napisanych skryptów, to jednak Microsoft wybrał JScripta - wypuszczając jego wersje na platformę .NET - JScript.NET. O powolnym umieraniu VBSa ciekawy wpis na blogu Erica Lipperta - Rumours of VBScript’s Death Have Been Greatly Exaggerated.

Warto pobrać sobie dokumentacje dla Windows Script 5.6, która w jednym pliku chm zawiera referencje dla VBS i JS oraz WSH, czyli o tym wszystkim o czym powinieneś wiedzieć bawiąc się skryptami w hoście skryptów Windowsa.

Garść informacji o skryptowaniu Windowsa można znaleźć też na Script Center, Natomiast dużo kodu w VBS dołączano w artykułach z cyklu Cześć Skrypciarze!. No i niezliczone zasoby dostępne są w różnych miejscach sieci…

Komentarze (2)

Fanael
20090707-145022-fanael

A najłatwiej to windowsa oskryptować PowerShellem ;)

Malcom
20090708-153959-malcom

Czy najłatwiej to chyba względnie od punktu widzenia. Bardzo mało używałem PS-a, więc dla mnie łatwiej jest innymi metodami, choćby Perlem ;)

A właśnie przez dyplomówkę zapodział się gdzieś kolejny wpis o skryptowaniu Windowsa, tym razem przy użyciu Perla.

Dodaj komentarz

/dozwolony markdown/

/nie zostanie opublikowany/