Centrum skryptów - Systemy operacyjne

Jak utworzyć listę wszystkich użytkowników danej jednostki organizacyjnej, którzy nie są uczestnikami grupy?

Udostępnij na: Facebook

Skrypciarze odpowiadają na Wasze pytania

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 utworzyć listę wszystkich użytkowników danej jednostki organizacyjnej, którzy nie są uczestnikami grupy?

Cześć, Skrypciarze! Jak utworzyć listę wszystkich użytkowników jednostki organizacyjnej, którzy nie należą do danej grupy?

-- TJ

Cześć, TJ! Tegoroczne edycja naszej Skrypciarskiej Olimpiady 2008 sprawia nam tyle frajdy, że postanowiliśmy ją przedłużyć do 6 marca, do godziny 8 rano. No dobra, oficjalnie zakończy się zgodnie z planem, czyli 3 marca, postanowiliśmy jednak dać Wam te trzy dodatkowe dni na poprawienie skryptów. Jeżeli więc z jakiejś konkurencji otrzymaliście 0 punktów, to zawsze możecie przesłać nam nową wersję po poprawkach i zero zamieni się magicznie na jakąś inną liczbę.

Oczywiście jeżeli zdążymy wysłać do Was wiadomość o punktach, bo może się okazać, że nie będziecie mogli nadesłać poprawionego skryptu z bardzo prostego powodu – nie będziecie wiedzieli, że trzeba go poprawić. Nie chodzi tu o nasze lenistwo – wczoraj testowanie skryptów zakończyliśmy gdzieś o 2 nad ranem. W tym roku mamy po prostu dwa razy więcej uczestników niż w roku ubiegłym, prosimy więc o wyrozumiałość. Tym bardziej z uwagi na fakt, że mamy dość mało wyrozumiały filtr przeciwspamowy, więc spora część z tego, co nam nadsyłacie kończy gdzieś w folderze „spam”, skąd ją trzeba odgrzebać.

Uwaga: Dlaczego tak się dzieje? Nasz filtr uznaje wiadomości z bezsensownym tekstem (chodzi tu o kody) za spam, bo jak wiecie zapewne, większość takiej poczty składa się z przypadkowych ciągów znaków. Nasz filtr jest trochę ignorantem lingwistycznym, nie włada ani VBScriptem, Perlem, ani Windows PowerShellem. Z tego samego powodu mimo wielu próśb w tej sprawie nie możemy wysyłać Wam artykułów Cześć, Skrypciarze jako codziennego newsletteru.

Jako że nasza Olimpiada oficjalnie kończy się w poniedziałek, dajemy Wam dodatkowo czas do czwartku na nadsyłanie poprawionych i upiększonych skryptów.

Uwaga: Ten przedłużony okres przydatności do spożycia skryptów dotyczy tylko i wyłącznie poprawek, jeżeli więc nie załapaliście się na naszą super Olimpiadę w tym roku, to nie ma szans na veni, vidi, vici w tym roku.

No chyba, że doślecie je do czwartku…

Tylko ani słowa do pani Redaktor!

Niestety żadna z konkurencji nie dotyczyła wypisania wszystkich użytkowników jednostki organizacyjnej, którzy nie należą do danej grupy w usłudze Active Directory. Gdyby jednak była taka konkurencja, to poniższy skrypt na pewno otrzymałby maksimum punktów:

Set objDictionary = CreateObject("Scripting.Dictionary")



Set objGroup = GetObject("LDAP://CN=Finance Users,OU=Finance,DC=fabrikam,DC=com")



For Each strMember in objGroup.Member

    objDictionary.Add strMember, strMember   

Next



Set objOU = GetObject("LDAP://OU=Finance,DC=fabrikam,DC=com")

objOU.Filter = Array("User")



For Each objUser in objOU

    strUser = objUser.distinguishedName    

    If Not objDictionary.Exists(strUser) Then

       Wscript.Echo strUser

    End If       

Next

Rozpoczynamy od utworzenia wystąpienia obiektu Scripting.Dictionary. Po co? Ponieważ listę użytkowników grupy przechowamy w słowniku (Dictionary). Po utworzeniu obiektu Dictionary łączymy się z grupą Finance Users usługi Active Directory za pomocą poniższego kodu:

Set objGroup = GetObject("LDAP://CN=Finance Users,OU=Finance,DC=fabrikam,DC=com")

Zanim sprawdzimy, którzy z uczestników nie należą do grupy Finance Users, musimy najpierw sprecyzować, którzy do niej należą. Na szczęście nie jest to skomplikowane, każda grupa Active Directory posiada bowiem atrybut Member, w którym przechowuje listę wszystkich uczestników grupy.

W celu otrzymania takiej listy musimy ustawić pętlę For Each, która przechodzi przez wszystkie elementy atrybutu Member:

For Each strMember in objGroup.Member

Wewnątrz pętli dodajemy nazwę uczestnika (a dokładniej jego nazwę wyróżniającą - distinguishedName) do słownika:

objDictionary.Add strMember, strMember

To niezbyt skomplikowane, korzystamy tu po prostu z metody Add oraz nazwy użytkownika (przechowanej w zmiennej pętli strMember) jako zarówno klucza obiektu Dictionary, jak i elementu Dictionary.

Po przejściu pętli obiekt Dictionary będzie zawierał listę wszystkich uczestników grupy Finance Users.

Kolejnym krokiem będzie pobranie wszystkich użytkowników danej jednostki organizacyjnej (w tym wypadku jednostki organizacyjnej Finance OU w fabrikam.com) i ustalenie, czy którykolwiek z tych użytkowników nie jest uczestnikiem grupy Finance Users. W tym celu łączymy się z jednostką organizacyjną w Active Directory, a następnie włączamy filtr (Filter) w celu przefiltrowania zwróconych danych. Filtr ten ogranicza nam dane do obiektów konta użytkowników:

objOU.Filter = Array("User")

Ustawiamy teraz kolejną pętlę For Each – ta pętla przechodzi przez całą kolekcję kont użytkowników, przechowywanych w jednostce organizacyjnej Finance. Wewnątrz tej pętli używamy następującego wiersza kodu, który pobiera nam wartość atrybutu distinguishedName użytkownika i przechowuje ją w zmiennej strUser:

strUser = objUser.distinguishedName

Dobre pytanie, dlaczego właśnie atrybut distinguishedName? Jak zapewne sobie przypominacie, atrybut Member przechowuje nazwę wyróżniającą każdego uczestnika grupy; oznacza to, że obiekt Dictionary również zawiera nazwę wyróżniającą każdego z użytkowników. Skąd wiemy, czy dany użytkownik jest uczestnikiem grupy Finance Users? Bardzo proste: sprawdzamy, czy nazwę wyróżniającą użytkownika można znaleźć w słowniku. Jeżeli można, to oznacza to, że użytkownik jest też uczestnikiem grupy. Do tego właśnie służy poniższy fragment kodu:

If Not objDictionary.Exists(strUser) Then

Korzystamy tu z metody Exists w celu ustalenia, czy nazwę wyróżniającą użytkownika (przechowywaną w zmiennej strUser) można znaleźć w obiekcie Dictionary. Jeżeli tak, to wracamy do początku pętli i powtarzamy cały dla kolejnego użytkownika jednostki Finance. Jeżeli nie, to wywołujemy echo nazwy wyróżniającej użytkownika:

Wscript.Echo strUser

Wracamy teraz do początku pętli i powtarzamy proces dla kolejnego użytkownika.

Po tych wszystkich komplikacjach powinniśmy otrzymać informację zwrotną na temat wszystkich nazw wyróżniających użytkowników jednostki organizacyjnej Finance, którzy nie są uczestnikami grupy Finance Users. Innymi słowy, powinniśmy otrzymać następujący wynik:

CN=Ken Myer,OU=Finance,DC=fabrikam,DC=com

CN=Pilar Ackerman,OU=Finance,DC=fabrikam,DC=com

CN=Jonathan Haas,OU=Finance,DC=fabrikam,DC=com

Wygląda dość głupio, nieprawdaż? Jeżeli się zgadzacie, to wypróbujcie trochę zmodyfikowaną wersję tego samego kodu:

For Each objUser in objOU

    strUser = objUser.distinguishedName 

    strUserName = objUser.displayName   

    If Not objDictionary.Exists(strUser) Then

       Wscript.Echo strUserName

    End If       

Next

Skrypt różni się dwiema rzeczami. Po pierwsze dodaliśmy wiersz kodu, który pobiera atrybut displayName użytkownika i przechowuje tę wartość w zmiennej strUserName:

strUserName = objUser.displayName

Po drugie, wewnątrz twierdzenia If umieszczamy nazwę wyświetlaną, a nie nazwę wyróżniającą:

Wscript.Echo strUserName

Wynik wygląda teraz trochę lepiej:

Ken Myer

Pilar Ackerman

Jonathan Haas

No dobrze, o wiele lepiej.

Pamiętaj TJ, że jeżeli nie zdążyłeś jeszcze nadesłać poprawionego skryptu to masz jeszcze trochę czasu. To żadne oszukiwanie, dążymy po prostu do doskonałości we wszystkim co robimy… Hmmm, to w sumie powinno stać się naszym mottem. Niech przynajmniej będzie nim na dzień dzisiejszy. Albo na tę godzinę, no dobra, kwadrans…

 Do początku strony Do początku strony

Centrum skryptów - Systemy operacyjne