Centrum Skrypciarzy - Systemy Operacyjne

Jak uzyskać listę wszystkich użytkowników, którzy mają uruchomiony proces na komputerze?

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 uzyskać listę wszystkich użytkowników, którzy mają uruchomiony proces na komputerze?

Cześć Skrypciarze! Pytanie

Cześć, Skrypciarze! Jak uzyskać listę wszystkich użytkowników, którzy mają uruchomiony proces na komputerze?

-- RE

Cześć Skrypciarze! Odpowiedź

Cześć, RE. Wiesz, w ciągu ostatnich 5 lat liczba osób oglądających wiadomości na głównych kanałach ostro spadła; liczba osób czytających codziennie gazetę spadła jeszcze bardziej dramatycznie. A w tym samym czasie, liczba osób odwiedzających codziennie Centrum Skryptów wzrosła w zawrotnym tempie. To może oznaczać tylko jedno: że kiedy ktoś szuka informacji i wiadomości, zwraca się do Skrypciarzy.

Jeżeli na przykład ktoś chce się dowiedzieć, jak uzyskać listę użytkowników, którzy mają uruchomiony jakiś proces na komputerze, to czy będzie szukać informacji na ten temat w telewizji albo w gazetach? Oczywiście, że nie. Znajdzie je w rubryce Cześć, Skrypciarze:

strComputer = "."



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

Set colProcessList = objWMIService.ExecQuery("Select * from Win32_Process")



Set objDictionary = CreateObject("Scripting.Dictionary")



For Each objProcess in colProcessList

    objProcess.GetOwner strNameOfUser, strUserDomain

    strOwner = strUserDomain & "\" & strNameOfUser



    If Not objDictionary.Exists(strOwner) Then

        objDictionary.Add strOwner, strOwner

    End If

Next



For Each strKey in objDictionary.Keys

    Wscript.Echo strKey

Next

Zatem: jak to działa? No cóż, skrypt rozpoczyna się od podłączenia do usługi WMI na lokalnym komputerze (chociaż możliwe jest też jego uruchomienie na komputerze zdalnym). Po utworzeniu połączenia stosujemy poniższy wiersz kodu w celu uzyskania kolekcji wszystkich procesów uruchomionych na danym komputerze:

Set colProcessList = objWMIService.ExecQuery("Select * From Win32_Process")

Mając kolekcję bezpiecznie zachowaną w zmiennej o nazwie colProcessList, tworzymy wystąpienie obiektu Scripting.Dictionary:

Set objDictionary = CreateObject("Scripting.Dictionary")

W jakim celu tworzymy wystąpienie obiektu Scripting.Dictionary? Cóż, zaraz do tego wrócimy. Przedtem jednak musimy uruchomić pętlę For Each, która przejdzie przez wszystkie procesy w naszej kolekcji. Wewnątrz tej pętli stosujemy poniższe dwa wiersze kodu:

objProcess.GetOwner strNameOfUser, strUserDomain

strOwner = strUserDomain & "\" & strNameOfUser

Co tu robimy? No cóż, z jakiegoś powodu klasa Win32_Process nie zawiera właściwości mówiącej, kto jest właścicielem procesu (właściciel procesu oznacza konto, na którym uruchomiony jest dany proces). Zamiast tego, dla każdego procesu w kolekcji musimy wywołać metodę GetOwner w celu określenia właściciela procesu. Jak widać, przy wywołaniu metody GetOwner podajemy dwa parametry; w naszym wypadku, strNameOfUser oraz strUserDomain. Są to parametry wyjściowe, czyli zmienne przekazywane do metody po to, by ta umieściła w nich odpowiednie wartości. W naszym skrypcie oznacza to, że metoda GetOwner przypisze nazwę właściciela procesu do zmiennej strNameOfUser, a następnie przypisze domenę tego użytkownika do zmiennej strUserDomain. No tak, te nazwy są całkowicie przypadkowe, możemy nadać parametrom out dowolne nazwy. Wolelibyśmy parametry out o nazwach x i y? Już się robi:

objProcess.GetOwner x, y

Ważne jednak tutaj są nie nazwy, ale kolejność: zmienna określona jako pierwsza otrzyma nazwę właściciela, a określona jako druga – domenę właściciela.

Kiedy już mamy tę informację, stosujemy drugi wiersz kodu, aby połączyć nazwę i domenę w formacie: Domena\Nazwa użytkownika (np., FABRIKAM\kenmyer). Całkiem proste, nieprawdaż?

Teraz kolej na następujący fragment kodu:

If Not objDictionary.Exists(strOwner) Then

    objDictionary.Add strOwner, strOwner

End If

Do gry wchodzi teraz obiekt Dictionary (słownik). Każdy proces uruchomiony na komputerze ma właściciela; jeżeli na komputerze jest uruchomionych 50 procesów, to jest też 50 właścicieli procesów. Jednak jest mało prawdopodobne, że będziemy mieli 50 różnych właścicieli; na pewno pojawią się duplikaty (na przykład, duży procent naszych procesów będzie uruchomiony na koncie NT AUTHORITY\SYSTEM). Naprawdę nie potrzebujemy – lub nie chcemy – oglądać wszystkich powtarzających się nazw. Ale jak wywołać echo w taki sposób, aby nazwy się nie powtarzały? Jednym ze sposobów jest właśnie obiekt Dictionary. Jak widać, w naszym pierwszym wierszu kodu stosujemy metodę Exists w celu określenia, czy właściciel pierwszego procesu (np. FABRIKAM\kenmyer) znajduje się w obiekcie Dictionary. Załóżmy, że właściciela tego procesu nie ma w obiekcie Dictionary. (Chyba nie trzeba wspominać, że pierwszy właściciel procesu nie pojawi się w Dictionary, ponieważ obiekt ten będzie pusty podczas pierwszego uruchomienia pętli.) W takim wypadku wywołujemy metodę Add w celu dodania właściciela procesu do obiektu Dictionary, używając przy tym zmiennej strOwner, aby określić wartości zarówno Key, jak i Item obiektu Dictionary:

objDictionary.Add strOwner, strOwner
Uwaga. Nie wiemy, jak działa obiekt Dictionary? Ktoś tu nie czytuje rubryki Sesame Script (j.ang.)

Następnie uruchamiamy pętlę i powtarzamy proces dla następnego procesu w kolekcji. Powiedzmy, że właścicielem procesu nr 2 jest FABRIKAM\kenmyer. Tym razem, kiedy wywołamy metodę Exists, właściciel procesu będzie w obiekcie Dictionary. Co się teraz stanie? Nic, po prostu kontynuujemy działanie pętli i powtarzamy procedurę dla trzeciego procesu w kolekcji.

Kiedy skończymy pobieranie informacji o właścicielach kolejnych procesów, wywołujemy echo wartości kluczy obiektu Dictionary. Niezwykłym zbiegiem okoliczności, te klucze to właśnie zbiór właścicieli procesów bez powtórzeń:

NT AUTHORITY\SYSTEM

NT AUTHORITY\NETWORK SERVICE

NT AUTHORITY\LOCAL SERVICE

FABRIKAM\kenmyer

No i mamy to, co chcieliśmy.

Uwaga: Jeżeli uruchomimy ten skrypt na komputerze z systemem Windows Vista, otrzymamy różne wyniki w zależności od tego, czy uruchomimy go jako administrator przy użyciu opcji Uruchom jako…, czy po prostu jako administrator. To nie ma sensu, prawda? Ale oznacza to, że jeżeli zalogowaliśmy się jako administrator, otwarliśmy wiersz poleceń i uruchomiliśmy skrypt, nie otrzymamy pełnej listy właścicieli procesów. Aby otrzymać pełną listę właścicieli, należy kliknąć prawym klawiszem myszy na skrót wiersza poleceń i wybrać opcję Run As Administrator. Jeżeli uruchomimy skrypt z tego okna, zobaczymy pełną listę właścicieli procesów.
 Do początku strony Do początku strony

 Centrum Skrypciarzy - Systemy Operacyjne