Centrum Skryptów - Active Directory

Jak zmodyfikować adresy e-mail wszystkich użytkowników w jednostce OU oraz jej podjednostkach?

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 zmodyfikować adresy e-mail wszystkich użytkowników w jednostce OU oraz jej podjednostkach?

Cześć, Skrypciarze! Muszę pobrać listę wszystkich użytkowników w jednostce OU oraz jej podjednostkach, a następnie zmienić adresy e-mail tak, aby zawierały wyłącznie małe litery. Jak to zrobić?

-- TB

Cześć, TB. Zanim odpowiedziałem na to pytanie, musiałem się dwa razy dobrze zastanowić. Bynajmniej nie dlatego, że to pytanie jest takie trudne; wcale nie jest. Nie dlatego również, że odpowiedź na nie nie zainteresuje zbyt wielu osób; zainteresuje. Chodzi o to, że to pytanie dotyczy wyszukania czegoś (kont użytkowników w usłudze katalogowej Active Directory), a ja w szukaniu nie jestem zbyt dobry. Tak naprawdę to jestem w tym bardzo kiepski. Przykład: w okresie świątecznym próbując schować prezent dla mojego syna tak naprawdę ukryłem go skutecznie przed samym sobą. Zobowiązałem się, że w imieniu dziadków kupię mu wypasione radio do samochodu i tak się przejąłem swoją rolą, że w decydującym momencie zapomniałem, gdzie ono jest. Nie było go tam, gdzie wydawało mi się, że je ukryłem. Po prostu zgubiłem prezent dla mojego syna. Pomimo wszelkich prób, nie udało mi się go znaleźć. To znaczy w końcu znalazłem. Musiałem się o niego potknąć, żeby go zauważyć. Nie macie pojęcia, co to za upokorzenie.

Swoja drogą, ciekawa historia, nie? A teraz do pracy. Potrzebny nam skrypt, który zmodyfikuje adresy e-mail dla wszystkich użytkowników w jednostce OU oraz jej podjednostkach:

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 AdsPath FROM 'LDAP://OU=Finance,DC=fabrikam,DC=com' WHERE objectCategory='user'"  

Set objRecordSet = objCommand.Execute



objRecordSet.MoveFirst

Do Until objRecordSet.EOF

    Set objUser = GetObject(objRecordSet.Fields("AdsPath").Value)

    strEmailAddress = objUser.Mail

    strEmailAddress = LCase(strEmailAddress)

    objUser.Mail = strEmailAddress

    objUser.SetInfo

    objRecordSet.MoveNext

Loop

Jak zwykle, nie omówię szczegółowo skryptów wyszukiwania usługi Active Directory; jeżeli potrzebne Wam są tego typu informacje, zajrzyjcie do dwuczęściowego artykułu Dude, Where’s My Printer? (j.ang.)

Uwaga. Dlaczego nigdy nie omawiam skryptów wyszukiwania usługi katalogowej Active Directory? Cóż, powinniście się tego domyślić na podstawie faktu, że napisaliśmy na ten temat dwa duże artykuły. To po prostu zbyt obszerny temat, aby go omówić w jednym artykule.

Zwłaszcza, jeżeli jest on pisany przez kogoś tak leniwego, jak ja.

Chciałbym jednak, żebyśmy zwrócili uwagę na inną rzecz, a mianowicie na kwerendę SQL, dzięki której pobierzemy informacje z usługi katalogowej Active Directory:

objCommand.CommandText = _

    "SELECT AdsPath FROM 'LDAP://OU=Finance,DC=fabrikam,DC=com' WHERE objectCategory='user'"

Dwie rzeczy powinny rzucić się nam w oczy. (A nawet trzy, jeżeli liczyć fakt, że dodałem klauzulę Where ograniczającą pobrane dane do obiektów o kategorii objectCategory równej user. Jak się zapewne sami domyślacie, to gwarantuje nam, że jedynymi obiektami przekazanymi przez kwerendę będą obiekty kont użytkowników.)

Na początek, zauważcie, że zaczynamy nasze wyszukiwanie w jednostce OU – Finance:

SELECT AdsPath FROM 'LDAP://OU=Finance,DC=fabrikam,DC=com' WHERE objectCategory='user

Czy to jest takie nadzwyczajne? Tak, ponieważ zazwyczaj zaczynamy wyszukiwanie w głównej domenie (DC=fabrikam,DC=com); a to dlatego, ze zazwyczaj przeszukujemy całą domenę. W tym skrypcie chcemy jednak przeszukać jednostkę OU Finance oraz jej podjednostki. Dlatego też zaczynamy wyszukiwanie w jednostce OU Finance, a nie w domenie głównej.

Słucham? Skąd skrypt ma wiedzieć, że ma przeszukać podjednostki jednostki OU Finance oraz samą jednostkę Finance? Cóż, na początku skryptu zdefiniowaliśmy stałą o nazwie AD_SCOPE_SUBTREE i ustawiliśmy jej wartość na 2; następnie przypisaliśmy tę stałą do właściwości Searchscope:

objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE

Dzięki temu skrypt wie, że ma przeszukać nie tylko jednostkę OU Finance (czyli nie tylko kontener docelowy), ale także wszelkie podjednostki OU lub podkontenery.

Proste, prawda?

Być może zauważyliście także, że jedyny szukany przez nas atrybut to ADsPath. Dlaczego nie szukaliśmy atrybutu mail, choć w skrypcie chodzi głównie o to, żeby zmodyfikować właśnie ten atrybut?

Dobre pytanie i przynajmniej ten jeden raz mam dla Was dobrą odpowiedź. Mimo że możliwe jest używanie technik bazodanowych do przeszukiwania usługi katalogowej Active Directory, nie można ich użyć do jej aktualizacji ani modyfikacji; innymi słowy, nie można napisać kwerendy Update, modyfikującej atrybut mail. Należy natomiast połączyć się indywidualnie z każdym kontem użytkownika i „ręcznie” zmodyfikować wartość atrybutu. (Nie martwcie się; choć to wygląda na bardzo żmudną pracę, w rzeczywistości idzie bardzo szybko). Do połączenia się z każdym kontem użytkownika z osobna wystarczy nam atrybut ADsPath; dlatego też tylko jego szukaliśmy. (Skrypciarze nie wiedzą, co to zachłanność. A przynajmniej nie są zachłanni, jeżeli chodzi o pobieranie informacji z usługi katalogowej Active Directory.)

Po wykonaniu naszej kwerendy uruchamiamy pętlę Do, która przejdzie przez wszystkie rekordy w otrzymanym zbiorze. Co zrobimy wewnątrz tej pętli? Oczywiście zastosujemy poniższy wiersz kodu w celu połączenia się z kontem pierwszego użytkownika:

Set objUser = GetObject(objRecordSet.Fields("AdsPath").Value)

Po utworzeniu tego połączenia pobieramy aktualny adres e-mail użytkownika i przypisujemy go do zmiennej o nazwie strEmailAddress:

strEmailAddress = objUser.Mail

Teraz używamy funkcji LCase języka VBScript w celu zamiany wszystkich dużych liter strEmailAddress na małe:

strEmailAddress = LCase(strEmailAddress)

Co otrzymujemy? Jeżeli adres e-mail wcześniej wyglądał tak:

KenMyer@Fabrkam.COM

Teraz będzie wyglądał tak, ponieważ duże litery zostały zamienione na małe:

kenmyer@fabrkam.com

Teraz wystarczy przypisać wartość zmiennej strEmailAddress do atrybutu mail użytkownika. Do tego posłuży nam ten oto wiersz kodu:

objUser.Mail = strEmailAddress

objUser.SetInfo

Jak sami widzicie, nie ma nic skomplikowanego w tych dwóch wierszach kodu: po prostu przypisujemy zmienną strEmailAddress do atrybutu Mail, a następnie wywołujemy metodę SetInfo w celu wpisania zmiany z powrotem do usługi katalogowej Active Directory. Zmodyfikowawszy adres e-mail dla pierwszego użytkownika w zbiorze rekordów, wywołujemy metodę MoveNext i powtarzamy proces dla następnego rekordu. Kiedy dojdziemy do końca zbioru rekordów i do końca pętli Do, będziemy mieli zmodyfikowane adresy e-mail wszystkich użytkowników w jednostce OU Finance oraz jej podjednostkach.

A przecież dokładnie o to nam chodziło.

Zastanawiacie się pewnie, jak mogłem się potknąć o ukryty prezent. Przecież to sugeruje, że wcale go nie schowałem. Otóż schowałem. Zawinąłem go dla niepoznaki w stary ręcznik i położyłem na środku pokoju, żeby o nim nie zapomnieć. Chyba tylko ja mogłem zrobić coś takiego.

 Do początku strony Do początku strony

Centrum Skryptów - Active Directory