Centrum skryptów - Systemy operacyjne

Jak sprawdzić czas aktywności usługi?

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 sprawdzić czas aktywności usługi?

Cześć Skrypciarze! Pytanie

Cześć, Skrypciarze! Jak mogę sprawdzić czas aktywności usługi?

-- JC

Cześć Skrypciarze! Odpowiedź

Cześć, JC. Podobno świadectwem tego, że przyswoiliśmy sobie pewną wiedzę jest fakt, że zapytani o coś w nocy o północy potrafimy bezbłędnie odpowiedzieć. Z kolei na temat Skrypciarzy krążą plotki, że są zdolni napisać żądany skrypt nawet przez sen. Można by się zastanowić, ile w tym prawdy. Ale po co? Istotne jest, że skrypty się sprawdzają. Jednakże niedowiarków możemy zapewnić, że Skrypciarz piszący te słowa nie ma w zwyczaju odpowiadać na pytania przed wypiciem mocnej kawy, która każdego postawiłaby na nogi.

Przyjrzyjmy się zatem poniższemu skryptowi, dzięki któremu możemy się dowiedzieć, kiedy dokładnie dana usługa została aktywowana. Mamy z nim pewien problem – skrypt nie przekazuje informacji o aktywacji usługi w sposób przyjazny dla użytkownika. Z tym jednak bardzo łatwo damy sobie radę, pomogą nam bowiem wyjaśnienia odnośnie podstaw dotyczących określania czasu aktywacji usług. Wszystko stanie się jasne.

A oto podstawowy skrypt pozwalający określić datę i godzinę pierwszej aktywacji usługi:

strComputer = "."



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



Set colServices = objWMIService.ExecQuery _

    ("Select * From Win32_Service Where Name = 'Spooler'")

 

For Each objService in colServices

    intProcessID = objService.ProcessID



    Set colProcesses = objWMIService.ExecQuery _

        ("Select * From Win32_Process Where ProcessID = " & intProcessID)



    For Each objProcess in colProcesses

        Wscript.Echo objProcess.CreationDate

    Next

Next

Jak widać, zaczynamy od podłączenia się do usługi WMI na lokalnym komputerze, chociaż możliwe jest także uruchomienie tego skryptu na zdalnym komputerze. (Nie macie czasem wrażenia, że po dwóch i pół latach istnienia naszej serii, nasze wypowiedzi zaczęły się powtarzać?!) Z uwagi na fakt, iż jesteśmy zainteresowani określeniem czasu aktywności tylko jednej usługi (w naszym wypadku usługi Print Spooler), wysyłamy zapytanie o kolekcję wszystkich usług, które mają nazwę Spooler (a ponieważ nazwy usług się nie powtarzają, istnieje tylko jedna usługa o tej nazwie):

Set colServices = objWMIService.ExecQuery _

    ("Select * From Win32_Service Where Name = 'Spooler'")

W idealnym świecie na tym byśmy poprzestali: uzyskalibyśmy datę i godzinę pierwszej aktywacji usługi. Miło by było, jednak klasa Win32_Service nie posiada właściwości mogącej nam powiedzieć, kiedy aktywowano usługę. Czy zatem oznacza to, że wszystko stracone? Owszem.

Ha-ha; My Skrypciarze czasem lubimy kogoś nabrać! W idealnym świecie skryptowania absolutnie nic nie zostaje stracone. Oczywiście to prawda, że klasa Win32_Service nie posiada właściwości, która mogłaby nam powiedzieć, kiedy aktywowano usługę, jednakże posiada ona właściwość informującą o ID procesu, w którym dana usługa została uruchomiona. Czy to nam pomoże? O tak, użyjemy identyfikatora procesu do wyszukania informacji z klasy Win32_Process. A czy to nam pomoże? Oczywiście, że tak: przecież klasa Win32_Service posiada właściwość (CreationDate), która powie nam, kiedy uruchomiony został proces.

Uwaga. Tylko nie dajmy się nabrać. Często się zdarza, że usługi zostają uruchomione w procesach dzielonych; pojedynczy proces może być hostem wielu usług, z których jedne mogły zostać uruchomione, a inne nie. Jednakże nic lepszego nie wymyślimy, chyba żebyśmy przeszukali systemowy dziennik zdarzeń i znaleźli zdarzenia mające związek, w tym przypadku, z usługą Print Spooler. Dziennik zdarzeń można przeszukać za pomocą kodu EventCode o wartości 7036, który rejestruje zmiany w statusie usługi.

Wracając do naszej kolekcji usług: stosujemy poniższy wiersz kodu, aby pobrać identyfikator procesu i zachować go w zmiennej o nazwie intProcessID:

intProcessID = objService.ProcessID

Teraz możemy uzyskać kolekcję wszystkich procesów mających ten określony identyfikator procesu (i znowu, w otrzymanej kolekcji znajdziemy tylko jeden element):

Set colProcesses = objWMIService.ExecQuery _

    ("Select * From Win32_Process Where ProcessID = " & intProcessID)

Następnie uruchamiamy pętlę For Each, która przejdzie przez tę kolekcję zawierającą jeden element. Wewnątrz pętli wywołujemy echo wartości właściwości CreationDate:

Wscript.Echo objProcess.CreationDate

W wyniku tego otrzymamy coś, co wygląda następująco:

20070227074100.796875-480

To właśnie mieliśmy na myśli mówiąc, że skrypt nie przekazuje informacji w sposób przyjazny dla użytkownika. Jednakże nie jest to wina skryptu, problem polega na tym, że usługa WMI zawsze przekazuje informację dacie i godzinie jako wartości UTC (Universal Time Coordinate). Ale czy możliwe jest przekonwertowanie wartości UTC na coś łatwiejszego do zrozumienia? Oczywiście, że tak:

strComputer = "."



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



Set colServices = objWMIService.ExecQuery _

    ("Select * From Win32_Service Where Name = 'Spooler'")

 

For Each objService in colServices

    intProcessID = objService.ProcessID



    Set colProcesses = objWMIService.ExecQuery _

        ("Select * From Win32_Process Where ProcessID = " & intProcessID)



    For Each objProcess in colProcesses

        dtmStartTime = objProcess.CreationDate



        dtmConvertedDate = CDate(Mid(dtmStartTime, 5, 2) & "/" & _

            Mid(dtmStartTime, 7, 2) & "/" & Left(dtmStartTime, 4) _

                & " " & Mid (dtmStartTime, 9, 2) & ":" & _

                    Mid(dtmStartTime, 11, 2) & ":" & Mid(dtmStartTime,13, 2))



        Wscript.Echo DateDiff("n", dtmConvertedDate, Now)

    Next

Next

Zrobiliśmy z tym zmodyfikowanym skryptem dwie rzeczy. Po pierwsze, zastosowaliśmy poniższy fragment kodu w celu przekonwertowania wartości właściwości CreationDate na wartość przedstawiającą „rzeczywistą” datę i godzinę:

dtmStartTime = objProcess.CreationDate



dtmConvertedDate = CDate(Mid(dtmStartTime, 5, 2) & "/" & _

    Mid(dtmStartTime, 7, 2) & "/" & Left(dtmStartTime, 4) _

        & " " & Mid (dtmStartTime, 9, 2) & ":" & _

            Mid(dtmStartTime, 11, 2) & ":" & Mid(dtmStartTime,13, 2))

Tego skryptu nie będziemy teraz omawiać w szczegółach, więcej informacji na temat konwertowania wartości UTC na wartość przedstawiającą datę i godzinę w standardowym formacie znaleźć można w tej części przewodnika Microsoft Windows 2000 Scripting Guide (j.ang.). Kiedy już przekonwertujemy wartość UTC na standardowy format daty i godziny, za pomocą funkcji DateDiff uzyskujemy liczbę minut, które upłynęły od uruchomienia procesu:

Wscript.Echo DateDiff("n", dtmConvertedDate, Now)

Jak widać, przekazujemy funkcji DateDiff trzy parametry:

  • n” wskazujący odstęp czasowy pomiędzy raportami. Tutaj raportujemy czas aktywności usługi w minutach, w celu uzyskania informacji o innych przerwach czasowych (sekund, godzin, dni) można zajrzeć do przewodnika Scripting Guide (j.ang.).
  • dtmConvertedDate, wartość daty i godziny otrzymaną z właściwości CreationDate.
  • Now, bieżącą datę i godzinę.

Ten zmodyfikowany skrypt raportuje ilość czasu w minutach, jaki upłynął od momentu uruchomienia procesu:

225

Jak mówiliśmy, nie jest to idealne rozwiązanie, jednakże warto jest mieć ten skrypt w zanadrzu. Działa on doskonale w przypadku usług uruchomionych w ramach własnych procesów; jest tak dlatego, że wyłączenie usługi powoduje także zatrzymanie procesu. A jak dowiedzieć się, które usługi są uruchomione w ramach własnych procesów? Oczywiście stosując poniższy skrypt:

strComputer = "."



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



Set colServices = objWMIService.ExecQuery _

    ("Select * From Win32_Service Where ServiceType = 'Own process'")

 

For Each objService in colServices

    Wscript.Echo objService.DisplayName

Next

I to już wszystko w tym temacie.

 Do początku strony Do początku strony

Centrum skryptów - Systemy operacyjne