Centrum skryptów - Systemy operacyjne

Jak przeprowadzić wyszukiwanie w usłudze Active Directory?

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 przeprowadzić wyszukiwanie w usłudze Active Directory?

Cześć Skrypciarze! Pytanie

Cześć, Skrypciarze! Właśnie zaczynam korzystanie z Windows PowerShell. Ogólnie biorąc bardzo mi się podoba, ale nie wiem, jak przeszukiwać Active Directory. Próbowałam dostosować stare skrypty języka VBScript, które znalazłam w Internecie, ale jest to żmudne i skomplikowane. Czy jest na to jakiś łatwiejszy sposób? Na początek chcę utworzyć listę wszystkich komputerów w Active Directory i wartości powiązanych z nimi atrybutów. Czy to możliwe?

-- SL

Cześć Skrypciarze! Pytanie

Cześć, SL! Ta cisza, którą słyszysz, to brak muzyki w moim biurze. Twoje pytanie wydało mi się tak ciekawe, że natychmiast zabrałem się do pracy. Z tego pośpiechu nie zjadłem śniadania ani nie włączyłem swojego Zune'a. Bierzmy się więc do roboty — zaczynam się robić głodny.

Na szczęście przeprowadzanie wyszukiwania w Active Directory przy użyciu Windows PowerShell to bułka z masłem. Skrypt, który napisałem jako przykład, nazywa się SearchAllComputersInDomain.ps1.

Ponieważ w tym tygodniu omawiamy przeszukiwanie Active Directory, podaję kilka źródeł związanych z tym informacji i skryptów. W witrynie Active Directory Script Center Hub (j.ang.) można znaleźć łącza prowadzące do różnych zasobów ułatwiających pracę z Active Directory. Sporą kolekcję skryptów ilustrujących wyszukiwanie w Active Directory można też znaleźć w tej sekcji (j.ang.) Repozytorium Skryptów. Kilka tego typu skryptów można też znaleźć w centrum skryptów udostępnianych przez użytkowników (j.ang.). Kolejnym źródłem są archiwalne artykuły z serii „Cześć, Skrypciarze” poświęcone usłudze Active Directory (j.ang.). I wreszcie odpowiednie zasoby można znaleźć w przewodniku po skryptach (j.ang.).

Skrypt SearchAllComputersInDomain.ps1 pozwala pobrać listę wszystkich atrybutów komputerów w domenie wraz z odpowiednimi wartościami:

Filter = "ObjectCategory=computer"

$Searcher = New-Object System.DirectoryServices.DirectorySearcher($Filter)

$Searcher.Findall() | 

Foreach-Object `

  -Begin { "Wyniki kwerendy $Filter: " } `

  -Process { $_.properties ; "`r"} `

  -End {"Liczba znalezionych wyników kwerendy $Filter" + [string]$Searcher.FindAll().Count }

Na początku skryptu tworzymy filtr wyszukiwania dialektu LDAP. Dokumentacja składni filtru wyszukiwania znajduje się w witrynie MSDN. W naszym skrypcie filtr jest prosty:

LDAPAttribute=value

Interesuje nas atrybut ObjectCategory, którego wartość to computer. ObjectCategory to nazwa atrybutu w usłudze Active Directory, a my podajemy dla tego atrybutu wartość computer. Proszę pamiętać, że brak spacji w filtrze ObjectCategory=computer może i wygląda dziwnie, ale ich dodanie spowodowałoby niepowodzenie filtra bez wygenerowania błędu. Po prostu nie otrzymalibyśmy żadnych wyników. Taka sytuacja może być bardzo niedogodna, ponieważ zdiagnozowanie problemu jest bardzo trudne. Filtr wyszukiwania przechowujemy w zmiennej $Filter, tak jak to widać poniżej:

$Filter = "ObjectCategory=computer"

Interesujący nas atrybut LDAP nazywa się ObjectCategory. Schemat atrybutu LDAP ObjectCategory informuje nas, że pod względem składni jest to wartość DistinguishedName. Możemy to sprawdzić, używając przystawki Schemat usługi Active Directory. Właściwości atrybutu ObjectCategory widać poniżej:

Przystawka Schemat usługi Active Directory domyslnie nie jest dostępna. Aby skorzystać z tego narzędzia, należy najpierw zarejestrować plik schmmgmt.dll, używając RegSvr32. Odpowiednie polecenie widać poniżej:

Regsvr32 schmmgmt.dll

Po zarejestrowaniu pliku schmmgmt.dll zostanie wyświetlone następujące okno dialogowe:

Jednak w naszej kwerendzie nie podajemy wartości DistinguishedName. Czy dokumentacja jest błędna? Jak właściwie działa nasz filtr? Otóż aparat wyszukiwania usługi Active Directory nieco ułatwia nam zadanie, umożliwiając użycie w filtrze nazwy wyświetlanej LDAP. Jeśli użyjemy jedynie parametru DisplayName, aparat wyszukiwania usługi Active Directory użyje definicji klasy i pobierze wartość defaultObjectCategory. Każdy obiekt classSchema ma atrybut o nazwie defaultObjectCategory, określający kategorię obiektu wystąpienia klasy, jeśli kategoria ta nie zostanie określona przez uzytkownika. W przypadku większości klas wartość atrybutu defaultObjectCategory jest tożsama z klasą. Jeśli w filtrze wyszukiwania określimy objectCategory = x, przy czym x będzie równe wartości atrybutu ldapDisplayName danej klasy, LDAP automatycznie rozwinie filtr, dokonując konwersji wartości objectCategory na format nazwy wyróżniającej. (Ten wywód zawdzięczam w dużym stopniu Luisowi z Lizbony — dzięki!).

A co z użyciem atrybutu objectClass zamiast objectCategory? Ze względu na strukturę klas w hierarchii usługi Active Directory, każdy obiekt Active Directory należy do wielu klas. Większość obiektów należy do czterech albo pięciu klas. Dlatego też indeks atrybutu objectClass jest bardzo duży. Ponadto atrybut objectClass ma słabą selektywność w przypadku wielu wartości klasy. Oprócz wolniejszego działania może to prowadzić do zwrócenia mylących wyników. Poniższa kwerenda zwraca zarówno obiekty typu komputer, jak i konta użytkowników:

PS C:\> $Filter = "ObjectClass=user"

PS C:\> $Searcher = New-Object System.DirectoryServices.DirectorySearcher($Filter)

PS C:\> $Searcher.FindAll()

Następnie musimy utworzyć wystąpienie klasy System.DirectoryServices.DirectorySearcher. Dokumentacja klasy DirectorySearcher znajduje się w witrynie MSDN. Istnieje wiele sposobów utworzenia klasy DirectorySearcher. Brandon, specjalista Microsoft MVP, zaleca podanie filtra w konstruktorze, ponieważ jest to znacznie szybsze w dużych sieciach. Przechowujemy zwrócony obiekt System.DirectoryServices.DirectorySearcher w zmiennej $Searcher:

$Searcher = New-Object System.DirectoryServices.DirectorySearcher($Filter)

Następnie używamy metody Findall, aby zwrócić wszystkie obiekty spełniające nasze kryteria filtru wyszukiwania:

$Searcher.Findall() |

Otrzymujemy wszystkie obiekty z metody Findall i przesyłamy je potokiem do apletu polecenia ForEach-Object. Używamy znaku gravisu (`), uzyskując kontynuację wiersza. Chcę, aby parametry –Begin, –Process i –End znalazły się w jednym wierszu. Znak ten działa tak samo, jak znak podkreślenia w języku VBScript. Polecenie ForEach-Object widać poniżej:

Foreach-Object

Chcemy użyć parametru –Begin z apletu polecenia ForEach-Object. Używamy parametru –Begin, aby wykonać coś jeden raz przed przesłaniem obiektów potokiem. Polecenia powiązane z parametrem –Begin w tym fragmencie skryptu są używane jeden raz dla wszystkich obiektów przechodzących przez potok. Jest to doskonałe miejsce na umieszczenie nagłówka — tekstu drukowanego u góry raportu lub wyświetlanego u góry ekranu. W ten sposób możemy wyświetlić wiadomość potwierdzającą, że są to wyniki kwerendy filtru. Widać to poniżej (proszę zwrócić uwagę, że na końcu wiersza ponownie używamy znaku kontynuacji):

-Begin { "Wyniki kwerendy $Filter: " }

Parametr –Process działa dla każdego obiektu przechodzącego przez potok. Wewnątrz tego fragmentu skryptu używamy średnika, aby wskazać, że pod względem logicznym jest to osobny wiersz kodu. Drukujemy właściwości i wartości każdego obiektu komputera, a następnie używamy znaku gravisa i litery r („`r”), aby umieścić pusty wiersz pomiędzy danymi poszczególnych komputerów. Na końcu tego fragmentu skryptu używamy gravisa, kontynuując w kolejnym wierszu:

-Process { $_.properties ; "`r"} `

Na koniec chcemy podać liczbę znalezionych kont komputerów. Dokonujemy konwersji liczby kont komputerów w ciąg znaków, który możemy dołączyć do reszty naszego komunikatu końcowego. Odpowiada za to poniższy wiersz kodu:

-End {"Liczba znalezionych wyników kwerendy $Filter" + [string]$Searcher.FindAll().Count }

Po uruchomieniu skryptu wyświetlony zostanie następujący komunikat podsumowania:

Cóż, SL, to już wszystko o wyszukiwaniu listy komputerów w domenie usługi Active Directory. Zapraszamy jutro — przez cały tydzień publikujemy artykuły o wyszukiwaniu w Active Directory. Do zobaczenia.

Skrypciarze Ed Wilson i Craig Liebendorfer

 Do początku strony Do początku strony

Centrum skryptów - Active Directory