Centrum Skryptów - Active Directory

Jak określić menedżera dla wszystkich grup w usłudze katalogowej Active Directory?

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 określić menedżera dla wszystkich grup w usłudze katalogowej Active Directory?

Cześć, Skrypciarze! Jak uzyskać listę wszystkich grup usługi katalogowej Active Directory wraz z nazwą użytkownika odpowiedzialnego za każdą grupę?

-- PL

Cześć, PL. Wiem, że większość z Was myśli sobie: „Rety, to naprawdę był bardzo pracowity miesiąc (j.ang.) dla Skrypciarzy. Zasługujecie na trochę wolnego”. Cóż, bardzo byśmy chcieli – że niby co? Nikt nie myśli, że powinniśmy dostać wolne? Zupełnie nikt? Absolutnie nikt? Mamo? Tato?

Mmmm ….

Cóż, i tak by z tego nic nie wyszło, ponieważ w chwili obecnej nie możemy sobie na to pozwolić. W końcu do Zimowej Olimpiady Skrypciarskiej 2008 (j.ang.) zostało niewiele czasu (15 lutego – 3 marca) i naprawdę mamy mnóstwo pracy, z tym, żeby się do niej przygotować. (Np. wymyślić konkurencje, które będą rozgrywane.) Jak możecie się spodziewać, chcemy, żeby Olimpiada 2008 była jeszcze większym wydarzeniem niż Olimpiada 2007.

Nagrody? Na pewno jakieś będą. Będą nie tylko nagrody, ale także Certyfikaty Doskonałości dla tych, którzy uzyskają co najmniej 60 punktów w jednej kategorii. Na pewno wszyscy będą się świetnie bawić.

Cóż, może poza Skrypciarzami, którzy będą musieli sprawdzać i podliczać wszystkie wyniki. Ale wszyscy inni powinni się świetnie bawić.

Dobre pytanie: w jaki sposób mamy pamiętać, że Olimpiada Skrypciarska zaczyna się 15 lutego? Możliwe jest, że jeszcze zdążymy wspomnieć o tym fakcie raz czy dwa. Ewentualnie, użytkownicy programu Microsoft Outlook mogą uruchomić poniższy skrypt i ustawić przypomnienie na czwartek, 14 lutego 2008 roku:

Const olAppointmentItem = 1

Set objOutlook = CreateObject("Outlook.Application")

Set objAppointment = objOutlook.CreateItem(olAppointmentItem)

objAppointment.Start = #2/15/2008 8:00 AM#

objAppointment.AllDayEvent = True

objAppointment.Subject = "2008 Winter Scripting Games"

objAppointment.Body = "The 2008 Winter Scripting Games begin at 8:00 AM Pacific Standard Time. " & _

    "Go to https://www.microsoft.com/scriptcenter/funzone/games.mspx to begin play. The Games end " & _

        "on Monday, March 3, 2008."

objAppointment.Location = "TechNet Script Center"

objAppointment.ReminderMinutesBeforeStart = 1440

objAppointment.ReminderSet = True

 

objAppointment.Save

W ten oto sposób możemy uzyskać listę grup usługi katalogowej Active Directory, razem z nazwą użytkownika odpowiedzialnego za każdą z tych grup. Dzięki i do zobaczenia jutro.

Ups, chyba mi się coś pomyliło. Listę grup usługi katalogowej Active Directory, razem z nazwą użytkownika odpowiedzialnego za każdą z tych grup możemy uzyskać za pomocą tego skryptu:

On Error Resume Next



Const ADS_SCOPE_SUBTREE = 2



Set objConnection = CreateObject("ADODB.Connection")

Set objCommand =   CreateObject("ADODB.Command")

objConnection.Provider = "ADsDSOObject"

objConnection.Open "Active Directory Provider"

Set objCommand.ActiveConnection = objConnection



objCommand.Properties("Page Size") = 1000

objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE 



objCommand.CommandText = _

    "SELECT Name, managedBy FROM 'LDAP://DC=fabrikam,DC=com' WHERE objectCategory='group'"



Set objRecordSet = objCommand.Execute



objRecordSet.MoveFirst



Do Until objRecordSet.EOF

    Wscript.Echo objRecordSet.Fields("Name").Value 

    Wscript.Echo objRecordSet.Fields("managedBy").Value

    Wscript.Echo

    objRecordSet.MoveNext

Loop

Teraz już nic mi się nie pomyliło.

Jak widzimy, jest to skrypt wyszukiwania usługi katalogowej Active Directory. A skoro to jest skrypt wyszukiwania usługi katalogowej Active Directory, może to oznaczać tylko jedno: nie będziemy dzisiaj szczegółowo omawiać skryptu. Dlaczego nie? No cóż, z jednej strony Skrypciarze są trochę leniwi (i na dodatek zasługują na wolne nawet, jeżeli nikt inny tak nie uważa). Co ważniejsze jednak, szczegółowa dyskusja na temat skryptów wyszukiwania Active Directory wykracza daleko poza to, co możemy zdziałać w jednym artykule rubryki Cześć Skrypciarze!. Nie rozpaczajcie jednak, mamy dwuczęściowy artykuł Tales from the Script (j.ang.), który zawiera wszelkie potrzebne informacje na temat wyszukiwania w usłudze Active Directory.

Uwaga, skąd ta skwaszona mina? Że niby nikogo nie obchodzi, czy użytkownicy powłoki Windows PowerShell mogą korzystać z wyszukiwania usługi katalogowej Active Directory? Głowa do góry: mnie obchodzi i tak w ogóle napisałem na ten temat cały artykuł (j.ang.) wyjaśniający, jak to zrobić. Ponadto, umieściliśmy ponad 100 przykładowych skryptów (j.ang.) na stronie Script Repository w Centrum Skryptów. Jak można było pomyśleć, że to nikogo nie obchodzi. Skrypciarzy takie rzeczy zawsze obchodzą!

Zamiast szczegółowego omawiania wyszukiwania Active Directory, przyjrzymy się dwóm częściom naszego skryptu: kwerendą SQL zastosowaną do pobrania informacji o grupie oraz pętlą Do Until zastosowaną do wyświetlenia tej informacji. Nasza kwerenda SQL wygląda tak:

objCommand.CommandText = _

    "SELECT Name, managedBy FROM 'LDAP://DC=fabrikam,DC=com' WHERE objectCategory='group'"

Jak widzimy, przeszukujemy całą domenę fabrikam.com, wydając skryptowi polecenie przekazania wartości dla dwóch atrybutów: Name oraz managedBy (atrybutu śledzącego, kto jest właścicielem grupy). Ta kwerenda zawiera także klauzulę Where, ograniczającą dane do obiektów posiadających wartość kategorii objectCategory równą group. Co nam to daje? Kwerendę SQL przekazującą nazwę i właściciela wszystkich grup z domeny fabrikam.com.

Czyli dokładnie to, czego od tej kwerendy wymagaliśmy.

Po wykonaniu tej kwerendy otrzymujemy zbiór rekordów zawierający żądane informacje. Kiedy już mamy te informacje, uruchamiamy pętlę Do Until. Która będzie działać dopóki właściwość EOF (end-of-file) zbioru rekordów nie uzyska wartości True. Wewnątrz tej pętli stosujemy poniższe dwa wiersze kodu w celu wywołania echa nazwy grupy oraz właściciela grupy:

Wscript.Echo objRecordSet.Fields("Name").Value 

Wscript.Echo objRecordSet.Fields("managedBy").Value

Następnie, stosujemy polecenie Wscript.Echo w celu wstawienia pustego wiersza w otrzymanych danych, po czym stosujemy metodę MoveNext w celu przejścia do następnego rekordu w zbiorze rekordów. (Nie można zapomnieć o wywołaniu metody MoveNext. Jeżeli tak się stanie, skrypt będzie w kółko wywoływał echo wartości pierwszego rekordu w zbiorze rekordów.) Po zakończeniu, powinniśmy otrzymać dane podobne do następujących:

Finance Department Employees

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



Finance Department Managers

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



Human Resources Employees

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

W ten oto sposób pobieramy listę grup usługi katalogowej Active Directory wraz z nazwą użytkownika odpowiedzialnego za każdą z tych grup. Dzięki i do zobaczenia jutro.

Już dobrze; słuszna uwaga. Jak widzimy, nasz przykładowy skrypt działał całkiem dobrze: przekazał nazwę każdej grupy wraz z jej właścicielem. Jedynym problemem jest to, że atrybut managedBy zachowuje właścicieli grup używając ich nazwy wyróżniającej; to oznacza, że otrzymujemy nazwy podobne do poniższych:

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

Nie ma z tym problemu, tylko w niektórych przypadkach wolelibyśmy otrzymać nazwy właścicieli wyświetlane w ten oto sposób:

Ken Myer

Z tym już jest pewien problem. Jest to nazwa wyświetlana, a atrybut managedBy nie zachowuje nazw wyświetlanych.

Czy to oznacza, że nie brakuje nam szczęścia? Skrypciarzom szczęścia brakuje od lat. (W końcu, gdybyśmy mieli choć odrobinę szczęścia, to przede wszystkim nie bylibyśmy Skrypciarzami.) Na szczęście jednak, szczęście nam nie jest potrzebne, żeby rozwiązać ten problem; wystarczy tylko zmodyfikować naszą pętlę Do Until, aby wyglądała tak:

Do Until objRecordSet.EOF

    Wscript.Echo objRecordSet.Fields("Name").Value 

    strUserDN = objRecordSet.Fields("managedBy").Value

    Set objUser = GetObject("LDAP://" & strUserDN)

    Wscript.Echo objUser.displayName

    Wscript.Echo

    objRecordSet.MoveNext

Loop

Co się zmieniło w tej pętli? Cóż, na początku nic: w pierwszym wierszu wywołujemy echo wartości atrybutu Name grupy, tak jak wcześniej. W wierszu 2 jednakże następują zmiany. Tym razem nie wywołujemy echa wartości atrybutu managedBy; zachowujemy natomiast tę wartość w zmiennej o nazwie strUserDN:

strUserDN = objRecordSet.Fields("managedBy").Value

Jaki jest cel tej czynności? Żaden, zrobiłem to, żeby mi czas do lunchu szybciej zleciał.

Zaraz, żartowałem przecież. Zawsze jest jakiś cel w działaniach Skrypciarzy. Pobieramy wartość nazwy wyróżniającej właściciela, ponieważ wtedy będziemy mogli przekazać tę wartość do funkcji GetObject i połączyć bezpośrednio z kontem użytkownika właściciela w usłudze katalogowej Active Directory:

Set objUser = GetObject("LDAP://" & strUserDN)

Jaki jest cel tego działania? Po połączeniu się z kontem użytkownika wywołujemy echo wszystkich wartości atrybutów dla tego konta. Jeżeli połączymy się z kontem grupy, będziemy mogli jedynie wywołać echo nazwy wyróżniającej właściciela grupy; jest tak dlatego (za pośrednictwem atrybutu managedBy), że jest to jedyna dostępna dla nas nazwa. Łącząc się z indywidualnym kontem użytkownika właściciela, możemy wywołać echo jakiejkolwiek wartości atrybutu dla tego konta, w tym displayName:

Wscript.Echo objUser.displayName

Dlaczego chcemy wywołać echo wartości atrybutu displayName? Ponieważ dzięki temu otrzymamy takie oto dane wyjściowe:

Finance Department Employees

Ken Myer



Finance Department Managers

Jonathan Haas



Human Resources Employees

Pilar Ackerman

Nieźle, nie?

Oczywiście można w prosty sposób zmodyfikować pierwotny skrypt, aby przekazał nam nazwy wszystkich grup zarządzanych przez określonego użytkownika. Wystarczy tylko uwzględnić nazwę wyróżniającą tego użytkownika w klauzuli Where, w taki oto sposób:

objCommand.CommandText = _

    "SELECT Name FROM 'LDAP://dc=fabrikam,dc=com' WHERE objectCategory=group' " & _

        "AND managedBy='CN=Ken Myer,OU=Finance,dc=fabrikam,dc=com'"

Dzięki tej kwerendzie otrzymamy listę grup zarządzanych przez użytkownika o nazwie Ken Meyer.

To powinno wystarczyć, PL.

Pamiętajcie, że Zimowa Olimpiada Skrypciarska już za kilka miesięcy (15 lutego 2008 – 3 marca 2008). Zaglądajcie od czasu do witryny internetowej Olimpady (j.ang.), będziemy tam co tydzień umieszczać wskazówki dotyczące tego, jak się do niej przygotować.

 Do początku strony Do początku strony

Centrum Skryptów - Active Directory