Centrum skryptów - Systemy operacyjne

Jak uruchomić proces i poczekać, aż zakończy pracę przed zakończeniem skryptu?

Udostępnij na: Facebook

Skrypciarze odpowiadają na Wasze pytania

Cześć Skrypciarze!

Witamy w rubryce TechNet, w której Skrypciarze z firmy Microsoft odpowiadają na częste pytania dotyczące używania skryptów w administracji systemu. Jeśli macie jakieś pytania z tej dziedziny, zachęcamy do wysłania e-maila na adres: scripter@microsoft.com. Nie możemy zagwarantować odpowiedzi na każde otrzymane pytanie, ale staramy się jak możemy.

Jak uruchomić proces i poczekać, aż zakończy pracę przed zakończeniem skryptu?

Hey, Scripting Guy! Question

Cześć Skrypciarze! Jak uruchomić proces i poczekać, aż zakończy pracę, przed zakończeniem skryptu?

-- FG

Hey, Scripting Guy! Answer

Hej, FG. Przed udzieleniem odpowiedzi, Skrypciarz, który pisze tę rubrykę musi coś wyznać: to on zepsuł wszystkim święta. Nie, żeby chciał, pamiętajcie, ale to nie ma znaczenia. Ważne, że to on zepsuł święta. Zeszłej nocy ten właśnie Skrypciarz oglądał telewizję, gdy zauważył reklamę delikatesów, w których wszystko działało jak w zegarku: wchodziłeś, składałeś zamówienie, dostawałeś jedzenie, płaciłeś i szczęśliwy szedłeś w swoją stronę, wszystko to w kilka sekund. I wszystko to przy skocznej muzyce.

Przynajmniej tak było, dopóki jakiś idiota nie miał czelności - nie uwierzycie - zapłacić za zakupy gotówką zamiast kartą bankomatową! Nie tylko idealnie zestrojony mechanizm delikatesów zatrzymał się ze zgrzytem, ale wyraz niesmaku na twarzy kasjera i pozostałych klientów dał jasno do zrozumienia, co wszyscy o tym sądzą: "Dzięki, facet. Nie dość, że zepsułeś święta sobie, to jeszcze musiałeś je zepsuć wszystkim na całym świecie. Mamy nadzieję, że jesteś zadowolony."

Jak pewno zgadliście, tym idiotą był Skrypciarz, który pisze tę rubrykę. To prawda: choć ma kartę bankomatową, to korzysta z niej jedynie w bankomatach. Gdy trzeba coś kupić, zawsze płaci gotówką. A gdy nadchodzi czas, by zapłacić rachunki, zawsze wypisuje czek, wkłada go do koperty, nakleja na kopertę znaczek i wysyła pocztą. (Lepiej usiądźcie, wyglądacie jakbyście mieli zemdleć.) Żadnych zleceń przelewu z konta, żadnych płatności przez Internet, wciąż spłaca rachunki tak samo, jak Neandertalczycy płacili za swoje rachunki.

Uwaga: OK, tu nas macie: nawet Neandertalczycy płacili przez telefon, kiedy tylko się dało.

Nie trzeba chyba mówić, że piszący tę rubrykę Skrypciarz pokornie przeprasza za prostackie i bezmyślne zachowanie i szczerze żałuje, że popsuł wszystkim święta.

Czy to znaczy, że tworzący tę rubrykę Skrypciarz w końcu pójdzie po rozum do głowy i dołączy do nowoczesnego świata? O nie, na Boga nie. Lubi być żywą skamieliną. Jednak, przynajmniej pokaże, jak napisać skrypt, który uruchamia proces, a potem czeka, aż zakończy on pracę:

strComputer = "."



Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2:Win32_Process")

objWMIService.Create "notepad.exe", null, null, intProcessID



Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")



Set colMonitoredProcesses = objWMIService.ExecNotificationQuery _

    ("Select * From __InstanceDeletionEvent Within 1 Where TargetInstance ISA 'Win32_Process'")



Do Until i = 1

    Set objLatestProcess = colMonitoredProcesses.NextEvent

    If objLatestProcess.TargetInstance.ProcessID = intProcessID Then

        i = 1

    End If

Loop



Wscript.Echo "Notepad został zamknięty."

Jak widzicie, zaczynamy od połączenia się z usługą WMI lokalnego komputera. Czy moglibyśmy uruchomić ten skrypt na komputerze zdalnym? Pewnie, moglibyśmy. Należy jednak pamiętać, że każdy proces uruchomiony na zdalnym komputerze będzie - z przyczyn bezpieczeństwa - działał w niewidzialnym oknie i nie pojawi się na ekranie. Oznacza to, że moglibyśmy użyć skryptu do wywołania narzędzi wiersza polecenia, które coś tam robią i automatycznie zakończyć skrypt, gdy skończą - to zadziała bez zastrzeżeń. Jeśli chodzi o aplikacje z interfejsem GUI, które zazwyczaj nie kończą pracy automatycznie, skrypt jest mniej przydatny, zwłaszcza uruchomiony na zdalnych komputerach. A to ponieważ aplikacja GUI uruchomi się w niewidocznym oknie, przez co będzie komuś znacznie trudniej zakończyć jej działanie.

Lecz niech nas to nie zniechęci: w przypadku narzędzi wiersza polecenia lub aplikacji uruchamianych na komputerze lokalnym, takie podejście sprawdza się doskonale.

Mówiąc o usłudze WMI - powinniśmy zaznaczyć, że tworząc połączenie do tej usługi, powinniśmy tworzyć powiązanie bezpośrednio do klasy Win32_Process:

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2:Win32_Process")

Dlaczego tak? Ponieważ, aby wywołać metodę Create i utworzyć nowy proces, musimy być połączeni z tą właśnie klasą. Typowe przy WMI podejście - skorzystanie z metody ExecQuery do pobrania kolekcji wszystkich egzemplarzy klasy - nic nam tu nie da.

Po stworzeniu połączenia, za pomocą następującego wiersza kodu tworzymy egzemplarz programu Notepad.exe (aplikacja GUI, ale OK: w tym przykładzie i tak uruchamiamy skrypt lokalnie). W tym wierszu kodu wywołujemy metodę Create, podając następnie nazwę pliku wykonywalnego, który chcemy uruchomić (Notepad.exe). Po nazwie pliku wykonywalnego następują dwa parametry null (parametry startowe nie użyte w skrypcie) oraz parametr wyjściowy o nazwie intProcessID:

objWMIService.Create "notepad.exe", null, null, intProcessID

Co to takiego było: parametr wyjściowy? Tak. Zazwyczaj podczas wywołania metody podaje się jej dane (parametry wejściowe), na przykład, nazwa pliku wykonywalnego (Notepad.exe) jest parametrem wejściowym. Za pomocą parametru wyjściowego metoda zwraca nam informacje; w tym przypadku identyfikator nowego procesu (PID). Musimy jedynie podać nazwę zmiennej w której będzie przechowywana ta informacja, całą resztą zajmie się metoda Create.

W tym miejscu chcemy, żeby skrypt się po prostu zatrzymał i poczekał, aż Notepad zakończy swoją pracę. W tym celu tworzymy drugą referencję do obiektu WMI (powtórnie korzystając ze zmiennej objWMIService) i za pomocą następującej kwerendy monitorujemy usuwanie procesów:

Set colMonitoredProcesses = objWMIService.ExecNotificationQuery _ 

    ("Select * From __InstanceDeletionEvent Within 1 Where TargetInstance ISA 'Win32_Process'")

Nie będziemy dziś omawiać skryptów monitorujących. Dodatkowe informacje są dostępne w emisji internetowej:An Ounce of Prevention: An Introduction to WMI Events. Wystarczy, że powiemy, że prosimy po prostu usługę WMI, by powiadomiła nas za każdym razem, gdy kasowany (kończony) jest jakiś proces. Chcielibyśmy też, żeby usługa WMI sprawdzała co sekundę, czy coś usunięto - temu służy parametr Within 1.

Po wywołaniu kwerendy tworzymy pętlę Do, która będzie wykonywana, aż zmienna i nie osiągnie wartości 1 (ponieważ i nie zostało zainicjalizowane, przyjmie wartość początkową 0):

Do Until i = 1 Set 

    objLatestProcess = colMonitoredProcesses.NextEvent 

    If objLatestProcess.TargetInstance.ProcessID = intProcessID Then 

        i = 1 

    End If 

Loop

Wewnątrz pętli korzystamy z następującego wiersza kodu, by poczekać, aż usługa WMI poinformuje nas o usunięciu procesu:

Set objLatestProcess = colMonitoredProcesses.NextEvent

Co się dzieje, gdy proces jest usuwany? W takim przypadku sprawdzamy, czy ProcessID skasowanego procesu (objLatestProcess.TargetInstance.ProcessID) jest równe wartości ProcessID stworzonego przez nas procesu:

If objLatestProcess.TargetInstance.ProcessID = intProcessID Then

Jeśli wartości są różne, przechodzimy do początku pętli i czekamy na powiadomienie o kolejnym skasowanym procesie. Jeśli wartości ProcessID są takie same, może to znaczyć tylko jedno: proces który stworzyliśmy został zakończony. W takim razie, przypisujemy zmiennej i wartość 1, co z kolei, powoduje opuszczenie pętli.

W tym miejscu po prostu wypisujemy komunikat informujący o zakończeniu pracy programu Notepad. Nie trzeba chyba mówić, że możecie w tym miejscu zrobić cokolwiek chcecie - w końcu to wasz skrypt. (Albo też nic nie robić - jeśli wolicie, możecie po prostu wyjść z pętli i skrypt automatycznie zakończy pracę).

Tak więc, czy tworzący tę rubrykę Skrypciarz zastanowi się chociaż nad używaniem karty bankomatowej do zakupów? Cóż, prawdę mówiąc, to wyglądało dużo szybciej i łatwiej niż płacenie gotówką. Oczywiście ludzie w reklamie po prostu przeciągali kartę i szli dalej: nie musieli wprowadzać numeru PIN, nie czekali na autoryzację i niczego nie musieli podpisywać. I żaden z nich nie pytał, czy mógłby dostać zwrot pieniędzy. Ale może nic z tego już się nie zdarza. W końcu, twórcy reklamy nigdy nie odważyliby się naciągnąć trochę prawdę, tylko po to, by ich produkt wyglądał lepiej. Broń Boże!

Wiecie co: Swięta już są popsute, ale zobaczymy, czy uda nam się uniknąć zepsucia Walentynek. Niczego nie możemy obiecać, ale zobaczymy.

 Do początku strony Do początku strony

Centrum skryptów - Systemy operacyjne