Centrum skryptów - Systemy operacyjne

Jak ustandaryzować nazwę logowania dla wszystkich użytkowników?

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 ustandaryzować nazwę logowania dla wszystkich użytkowników?

Cześć, Skrypciarze! Muszę zmienić nazwy logowania usługi Active Directory używane w firmie z formatu kmyer na format Ken.Myer. Czy można to zrobić za pomocą skryptu?

-- DO

Cześć, DO. Wiecie wszyscy dobrze, że czasem zdarza mi się sugerować, jakoby moje życie było szare i nudne, i że narzekam, że nic ekscytującego nigdy mi się nie przydarza. Cóż, szczerze mówiąc trochę z tym przesadzałem. Jak się okazuje, ekscytujące rzeczy ciągle mi się przydarzają.

Ciągle.

Na przykład ostatnio w sklepie spożywczym koło mojego domu otwarto nowy bar z koktajlami mlecznymi Jamba Juice (j.ang.). Przyznaję, że sam ten fakt wydaje się wcale nie być wcale emocjonujący. Chociaż osobiście nie mam nic przeciwko koktajlom mlecznym, nie czuję nieodpartej potrzeby picia koktajlu mlecznego podczas robienia zakupów w spożywczym (nie, nawet jeżeli nazywa się on „Pomarańczowa rozkosz” lub „Truskawkowe zapomnienie”).

To, co jest tak ekscytujące lub przynajmniej trochę interesujące – co w sumie stanowi jedyną atrakcję w moim życiu ostatnimi czasy – to reakcja innych klientów tego sklepu: kolejka przy barze z koktajlami jest niemal taka sama, a czasem nawet dłuższa – niż kolejka przy ciastkarni (która także jest zlokalizowana wewnątrz sklepu). I to nie dlatego, że ludzie wstąpili po to, żeby kupić koktajl czy ciastko i zabrać je na wynos. Spożywają je będąc w sklepie. A tak w ogóle, wszystkie wózki w sklepie zostały ostatnio wyposażone w uchwyty na kubki.

Nie, zaraz. podwójne uchwyty. Takie na kubek i z podstawką na ciastko. widziałem niejednego klienta z koktajlem w jednej i szarlotką w drugiej ręce.

W sumie, to przecież nie ma w tym nic złego. Wydaje mi się zabawne, że żeby przetrwać zakupy potrzebny jest koktajl mleczny i szarlotka. Trochę tego nie rozumiem.

Uwaga. Biorąc pod uwagę ceny artykułów sklepowych, bardziej zrozumiałe byłoby dla mnie, gdyby ludzie potrzebowali zamiast koktajlu pięćdziesiątkę wódki, żeby przetrwać te zakupy.

Przyznaję, że w tym sklepie są alejki, do których ja osobiście się nie zbliżam (na przykład ta, w której są owoce morza). O ile mi wiadomo, jedyną rzeczą, której nie można jeszcze kupić w spożywczym są skrypty umożliwiające zmianę nazwy sAMAccountName dla wszystkich użytkowników w domenie.

Ale nic nie szkodzi. Od tego są w końcu Skrypciarze:

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://dc=fabrikam,dc=com' WHERE objectClass='user'"  



Set objRecordSet = objCommand.Execute



objRecordSet.MoveFirst



Do Until objRecordSet.EOF

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

    strOldName = objUser.sAMAccountName

    strNewName = objUser.givenName & "." & objUser.sn

    objUser.sAMAccountName = strNewName

    objUser.SetInfo

    Wscript.Echo strOldName & vbTab & strNewName

    objRecordSet.MoveNext

Loop

Zanim wyjaśnię sposób działania tego skryptu, chcę zauważyć, że w rzeczywistym świecie to zadanie może być odrobinę bardziej skomplikowane, niż sugeruje to nasze proponowane rozwiązanie. Po pierwsze, zakładamy, że imiona (atrybut givenName) oraz nazwisko (atrybut sn) zostały już przypisane do wszystkich użytkowników. Jeżeli nie, od razu napotkamy problemy podczas próby utworzenia nowej nazwy logowania (sAMAccountName), która łączy nieistniejące imię i nieistniejące nazwisko. Jednym ze sposobów obejścia tego problemu jest pobranie kont użytkowników za pomocą poniższej kwerendy:

objCommand.CommandText = _

    "SELECT AdsPath FROM 'LDAP://dc=wingroup,dc=windeploy,dc=ntdev,dc=microsoft,dc=com' " & _

        "WHERE objectClass='user' AND givenName = '*' AND sn = '*'"

Ta kwerenda przekazuje nam tylko te konta użytkowników (objectClass = 'user'), w których użytkownik ma zarówno imię (givenName = '*') jak i nazwisko (sn = '*'). Ewentualnie moglibyśmy użyć poniższej kwerendy w celu pobrania kolekcji wszystkich użytkowników, którzy nie mają przypisanego imienia lub nazwiska:

objCommand.CommandText = _

    "SELECT AdsPath FROM 'LDAP://dc=wingroup,dc=windeploy,dc=ntdev,dc=microsoft,dc=com' WHERE " & _

        objectClass='user' AND (givenName <> '*' OR sn <> '*')"

Ale to zależy tylko od Was. W naszym skrypcie zakładamy, że konta użytkowników mają przypisane imiona i nazwiska.

Zaraz, zaraz. To jeszcze nie koniec. Nie powiedziałem Wam jeszcze o możliwości wystąpienia dwóch użytkowników o identycznych imionach i nazwiskach. Na przykład dwóch różnych osobach nazywających się Ken Myer. To jest problem, ponieważ skrypt spróbuje przypisać obydwu użytkownikom tę samą nazwę logowania: Ken.Myer. A tego nie chcemy: nazwy logowania nie mogą się w domenie powtarzać. Jak można obejść ten problem? Jedną z możliwości jest utworzenie proponowanej nazwy sAMAccountName, a następnie – przed przypisaniem jej do użytkownika - wykonanie szybkiego sprawdzenia w usłudze Active Directory, czy ta nazwa jest już używana. Jeżeli nie jest używana, nie ma o czym mówić. Jeżeli jest, musimy coś z nią zrobić (np. dodać 1 na początku), żeby się nie powtarzała. To trochę wykracza poza to, co możemy dzisiaj zrobić, ale jeżeli ktoś chce wiedzieć, jak to zrobić, dajcie nam znać i omówimy to w którejś rubryce w przyszłości.

Zakładając oczywiście, że nie zrobi tego wcześniej personel sklepu spożywczego.

W dzisiejszym artykule zakładamy, że nie mamy tego problemu (dla osób pracujących w firmie Microsoft było to do przewidzenie. My tutaj nie mamy żadnych problemów). Zrobimy tez to, co zawsze robimy, czyli: pominiemy wyjaśnienia dotyczące wykonywania wyszukiwania w usłudze Active Directory. Dlaczego pomijamy te wyjaśnienia? To proste: te informacje są szczegółowo opisane w naszym dwuczęściowym artykule Dude, Where’s My Printer? (j.ang.). Jedyne, co tutaj zrobimy, to zerkniemy na chwilę na kwerendę, która przekazuje nam kolekcję wszystkich kont użytkowników w domenie fabrikam.com:

objCommand.CommandText = _

    "SELECT ADsPath FROM 'LDAP://dc=fabrikam,dc=com' WHERE objectClass='user'"

Jak widać, nie ma w tym zupełnie nic skomplikowanego: pobieramy po prostu kolekcję wszystkich obiektów w usłudze Active Directory z klasą objectClass o wartości user. Zauważyliście także zapewne, że informujemy skrypt, że ma nam przekazać tylko wartość jednego atrybutu: ADsPath, właściwość umożliwiającą nam zlokalizowanie określonego obiektu w usłudze Active Directory. To może wydawać się dziwne. Przecież jeżeli pracujemy z atrybutami sAMAccountName, givenName oraz sn, to czy nie powinniśmy pobrać także wartości tych właściwości?

Cóż, mieliście prawo tak pomyśleć. Jak się jednak okazuje, wyszukiwanie w usłudze Active Directory może odbywać się tylko w trybie do odczytu. Nie można wprowadzać zmian ani aktualizacji w obiektach za pomocą kwerendy (zła wiadomość dla tych, którzy są przyzwyczajeni do używania poleceń języka SQL, takich jak UPDATE). Za każdym razem, gdy chcemy zmodyfikować obiekt w usłudze Active Directory, musimy połączyć się bezpośrednio z tym obiektem. Część naszego skryptu dotycząca wyszukiwania ułatwia pobranie lokalizacji dla wszystkich obiektów kont użytkowników, ale to wszystko, co może dla nas zrobić. Nadal musimy połączyć się z bieżącym kontem użytkownika w celu dokonania zmiany nazwy sAMAccountName. Nie pobraliśmy wartości atrybutów sAMAccountName, givenName oraz sn z prostego powodu: w tym momencie i tak nie możemy nic z nimi zrobić.

Ale nie martwcie się. To się zaraz zmieni.

Po zdefiniowaniu kwerendy używamy następującego wiersza kodu (oraz metody Execute) w celu pobrania zestawu rekordów składającego się z wszystkich kont użytkowników w domenie fabrikam.com:

Set objRecordSet = objCommand.Execute

Teraz wywołujemy metodę MoveFirst w celu przejścia do pierwszego rekordu w zestawie rekordów, a następnie uruchamiamy pętlę Do Until, która będzie działać dopóki nie przejdzie przez każdy z tych rekordów, czyli dopóki wartość właściwości EOF (end-of-file) zestawu rekordów się nie zmieni.

Do Until objRecordSet.EOF

Co robimy wewnątrz tego zestawu rekordów? Wiecie co? To wyjaśnienie trwa już jakiś czas, może skoczycie po koktajl Jabłkowe spełnienie marzeń i do tego sernik z owocami i za chwilę wrócimy do naszego skryptu?

A tak, i przepraszam, że ta rubryka nie ma wbudowanych uchwytów na kubki i podstawek na ciastka. Ale już nad tym pracujemy.

OK, więc co robimy wewnątrz tego zestawu rekordów? Najpierw wykorzystujemy wartość Value atrybutu ADsPath dla pierwszego rekordu i używamy jej w celu połączenia się z bieżącym kontem użytkownika w usłudze Active Directory:

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

Po utworzeniu połączenia pobieramy istniejącą nazwę sAMAccountName użytkownika i zachowujemy ją w zmiennej o nazwie strOldName:

strOldName = objUser.sAMAccountName

Następnie używamy poniższego wiersza kodu w celu utworzenia nowej nazwy sAMAccountName dla użytkownika:

strNewName = objUser.givenName & "." & objUser.sn

I znowu, nie ma w tym nic skomplikowanego: pobieramy po prostu imię użytkownika (givenName), dodajemy kropkę i do togo dodajemy nazwisko użytkownika (sn). Wynik? Użytkownik o imieniu Ken i nazwisku Myer otrzymuje nazwę sAMAccountName wyglądającą tak:

Ken.Myer

Jakimś cudem jest to dokładnie taka nazwa sAMAccountName, jaką powinien mieć Ken Myer.

Teraz wystarczy przypisać nową wartość do nazwy sAMAccountName Kena, a następnie wywołać metodę SetInfo w celu wpisania tych zmian do usługi Active Directory:

objUser.sAMAccountName = strNewName

objUser.SetInfo

Ale oczywiście nie możemy tego tak zostawić. Wywołujemy echo starej i nowej nazwy sAMAccountName Kena:

Wscript.Echo strOldName & vbTab & strNewName

Dzięki temu otrzymamy raport podobny do poniższego, który pomaga śledzić wszystkie wprowadzone zmiany:

Kmyer    Ken.Myer

packerman    Pilar.Ackerman

jhaas    Jonathan.Haas

W tym momencie wywołujemy metodę MoveNext w celu przejścia do następnego rekordu w zestawie rekordów, a następnie wracamy na początek pętli i powtarzamy cały proces dla użytkownika Nr 2. Możecie wierzyć lub nie, ale to wszystko, co należało zrobić.

Na wypadek, gdyby ktoś się zastanawiał, w moim sklepie spożywczym mogę zrobić następujące rzeczy:

  • Kupić koktajl mleczny Jamba Juice.
  • Kupić ciasto.
  • Kupić Chińszczyznę na wynos i kanapki Oskar.
  • Kupić benzynę.
  • Wypożyczyć film.
  • Wziąć pożyczkę lub kredyt mieszkaniowy.
  • Wysłać bukiet kwiatów.

Jak widzicie, jedyne, czego brakuje na tej liście to „kupić coś na obiad". Ale przecież nie można się spodziewać, że w spożywczym można załatwić wszystko.

 Do początku strony Do początku strony

Centrum skryptów - Systemy operacyjne