Centrum Skrypciarzy - Systemy Operacyjne

Jak uzyskać listę wszystkich użytkowników lokalnych, mających wygasające hasło?

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 lokalnych, mających wygasające hasło?

Cześć Skrypciarze! Pytanie

Cześć, Skrypciarze! Jak uzyskać listę wszystkich użytkowników lokalnych, mających wygasające hasło?

-- JM

Cześć Skrypciarze! Odpowiedź

Cześć, JM. Dzięki za pytanie. Zanim jednak na nie odpowiemy, mamy pytanie do Ciebie: czy nie masz przypadkiem kostki do gry na zbyciu? Tak, kostki – takiej, jakiej się zazwyczaj używa w grach planszowych i tym podobnych. Okazuje się, że Skrypciarze pilnie potrzebują kostek do gry, a tak w ogóle to potrzebują ich ok. tysiąc, i to natychmiast. Niestety mają pewne problemy ze zlokalizowaniem takiej liczby kostek za przystępną cenę.

A po co Skrypciarzom kostki do gry? Nic wielkiego. W końcu są programistami w firmie Microsoft, a 1000 kostek do gry to standardowe wyposażenie programisty. Ciężko jest być Skrypciarzem, a bez kostek to w ogóle szkoda gadać. Nie można normalnie funkcjonować jako Skrypciarz, nie mając kostek. Tak czy siak, jeżeli przypadkiem znajdziesz się w posiadaniu zbędnych kostek, chętnie Cię od nich uwolnimy. Dotyczy to każdego, kto czyta te słowa. Prosimy o przesyłanie kostek do gry w dowolnych kolorach i o dowolnych kształtach pod poniższy adres:

Microsoft Scripting Guys
Microsoft Corporation
Building 42/4039
One Microsoft Way
Redmond, WA 98052
USA

Oczywiście Skrypciarze nie mają zamiaru nawet prosić o coś, nie dając nic w zamian. Zobaczmy, co my tu mamy. Otóż mamy skrypt, dzięki któremu można uzyskać listę lokalnych użytkowników mających wygasające hasło:

Const ADS_UF_DONT_EXPIRE_PASSWD = &H10000

 

strComputer = "atl-ws-01"



Set colAccounts = GetObject("WinNT://" & strComputer & "")



colAccounts.Filter = Array("user")



For Each objUser In colAccounts

    If Not objUser.UserFlags AND ADS_UF_DONT_EXPIRE_PASSWD Then

        Wscript.Echo objUser.Name

    End If

Next

No dobra, zobaczmy, czy uda nam się rozszyfrować, jak to maleństwo działa. Jak widać, zaczynamy od określenia stałej o nazwie ADS_UF_DONT_EXPIRE_PASSWD (piękne imię, prawda?) i nadajemy jej wartość &H10000. Tak, to prawda, ta stała pomoże nam określić, czy użytkownik ma wygasające hasło. Następnie przypisujemy nazwę komputera (tego, na którym znajdują się lokalne konta) do zmiennej o nazwie strComputer i stosujemy poniższy wiersz kodu do połączenia się z menedżerem System Account Manager (SAM) komputera:

Set colAccounts = GetObject("WinNT://" & strComputer & "")

Domyślnie, takie połączenie z menedżerem SAM pozwala uzyskać informacje o wszystkich lokalnych kontach użytkowników na komputerze; uzyskujemy także informacje o lokalnych grupach na tym komputerze, wszystkich zainstalowanych na nim usługach, drukarkach itd. Tak naprawdę, te rzeczy nas nie interesują; obchodzą nas tylko konta użytkowników. (Koledzy piszącego te słowa Skrypciarza mogą poświadczyć, że dla niego najważniejsi są zawsze ludzie.) Dlatego też naszym następnym krokiem jest zastosowanie filtra (Filter), który ograniczy zakres pobieranych danych do tych, które dotyczą kont użytkowników:

colAccounts.Filter = Array("user")

Dobre pytanie: dlaczego pobraliśmy kolekcję wszystkich użytkowników kont? Czyż nie byłoby prościej i szybciej, gdybyśmy napisali zapytanie SQL, które przeszuka lokalny komputer i przekaże nam kolekcję składającą się tylko z użytkowników posiadających wygasające hasło? Prawdę mówiąc, tak, to byłoby o wiele prostsze i szybsze. Niestety, jest z tym podejściem pewien problem: nie działa. Inaczej niż w usłudze Active Direktory, nie możemy uruchomić zapytań SQL w stosunku do menedżera SAM. Wskutek tego, kiedy chcemy zrobić coś z lokalnymi kontami, musimy uciec się do bardziej tradycyjnych metod: pobieramy kolekcję wszystkich kont, a następnie sprawdzamy po kolei, czy użytkownik któregoś z nich ma wygasające hasło.

I tak się składa, że dzięki temu przechodzimy do następnej części naszego skryptu. Po uruchomieniu pętli For Each, która przejdzie przez każde konto z kolekcji, stosujemy poniższy wiersz kodu:

If Not objUser.UserFlags AND ADS_UF_DONT_EXPIRE_PASSWD Then

Możecie wierzyć albo nie, ale sprawdzimy teraz, czy hasło użytkownika w ogóle wygasa. Informacja o wygasaniu hasła zawarta jest w atrybucie maski bitowej o nazwie UserFlags. Gdyby ktoś nie wiedział, czym jest atrybut maski bitowej; taki typ atrybutu to jedna właściwość, która może posiadać wiele wartości. (Kompletna lista wartości zachowanych w atrybucie UserFlags, patrz dokumentacja dotycząca WinNT User Object w programie MSDN.) Jak jedna właściwość może zawierać kilka wartości? No cóż, krótko mówiąc, maska bitowa składa się z serii „przełączników”, z których każdy zawiera niepowtarzalną wartość (w tym przypadku, przełącznik dla wygasających haseł ma wartość &H10000). Jeżeli dany przełącznik jest włączony, oznacza to, że właściwość jest uruchomiona; jeżeli przełącznik jest wyłączony, właściwość jest zablokowana. Składnia dla sprawdzania wartości przełącznika jest odrobinę nieporęczna, jednak poniższy fragment kodu mówi nam, czy użytkownik ma niewygasające hasło (czyli, czy przełącznik ADS_UF_DONT_EXPIRE_PASSWD jest włączony):

objUser.UserFlags AND ADS_UF_DONT_EXPIRE_PASSWD

Słuszna uwaga: nie jesteśmy zainteresowani użytkownikami mającymi niewygasające hasło, nieprawdaż? Dlatego też zastosowaliśmy też równie nieporęczną składnię If Not:

If Not objUser.UserFlags AND ADS_UF_DONT_EXPIRE_PASSWD Then

W ten sposób skrypt VBScript przekazuje informację: „Jeżeli użytkownik nie ma niewygasającego hasła, zastosuj następny fragment kodu”.

Uwaga. Dlaczego zatem VBScript nie przekazał po prostu tej informacji, zamiast zmuszać nas do użycia dziwacznej składni If Not? Nie wiemy. I pewnie nigdy się nie dowiemy.

Jeżeli się okaże, że użytkownik rzeczywiście posiada wygasające hasło, stosujemy poniższy wiersz kodu w celu wywołania echa nazwy użytkownika:

Wscript.Echo objUser.Name

Następnie wracamy na początek pętli, gdzie powtarzamy proces dla następnego elementu z kolekcji.

A do czego nam tysiąc kostek? No cóż, szczerze mówiąc, potrzebujemy dwóch tysięcy, ale postanowiliśmy skromnie zacząć od tysiąca i potem zobaczyć, co będzie dalej. Ale nie powiemy, o co chodzi; to zepsułoby niespodziankę!

 Do początku strony Do początku strony

Centrum Skrypciarzy - Systemy Operacyjne