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