Centrum skryptów - Systemy operacyjne

Jak zmienić mapowanie dysków sieciowych, aby używały adresu IP zamiast nazwy komputera? 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 zmienić mapowanie dysków sieciowych, aby używały adresu IP zamiast nazwy komputera?

Cześć Skrypciarze! Pytanie

Cześć, Skrypciarze! Jak przemapować dyski sieciowe tak, aby wskazywały na adres IP zdalnego komputera a nie nazwę komputera?

-- YM

Cześć Skrypciarze! Odpowiedź

Cześć, YM. Wiecie, wczorajszą rubrykę rozpoczęliśmy od słów „nieważne”, odnosząc się do faktu, że we wcześniejszym artykule piszący te słowa Skrypciarz lamentował, że nic interesującego mu się ostatnio nie przydarza. Więc jak zaczniemy dzisiejszy artykuł? Właśnie tak: „nieważne”.

Wczoraj zauważyliśmy, że piszący te słowa Skrypciarz był … szczęśliwym … właścicielem samochodu, który „odmówił współpracy”. Zgodnie ze wstępną diagnozą, zepsuł się układ ECM (który, jak się okazuje, tak naprawdę nazywa się ECU), a piszący te słowa Skrypciarz obecnie przyzwyczaja się do myśli, że jest „Skrypciarzem, który właśnie wydał kilka tysięcy dolców, żeby naprawić swój głupi samochód”.

W tym momencie powinniśmy wyjaśnić, że co do zepsucia się samochodu nie było żadnych wątpliwości: nawet mechanikom nie udało się go uruchomić, czy choćby sprawić, że „prawie” zaskoczył. Kiedy jednak mechanicy uruchomili swoje komputerowe narzędzia diagnostyczne, wszystko stało się jasne: z pozoru z samochodem było absolutnie wszystko w porządku. (No cóż, pomijając fakt, że nie chciał się uruchomić.) Niezależnie od tego, czego próbowali mechanicy, nie mogli znaleźć problemu. Z samochodem nie było absolutnie żadnego problemu. Po prostu nie chciał się uruchomić.

W pewnym momencie któryś z mechaników zauważył, że jeden z bezpieczników jest spalony. Ten bezpiecznik był odpowiedzialny za wyświetlanie komunikatów ostrzegawczych; nie ma on nic wspólnego z uruchomieniem samochodu. A jednak po wymianie bezpiecznika samochód zapalił od razu. „To nie ma żadnego sensu” powiedział mechanik. „Nie mam pojęcia dlaczego właśnie to załatwiło cały problem. Tak naprawdę nie ma takiej opcji, żeby to właśnie załatwiło ten problem. To nie ma w ogóle żadnego sensu.”

A jednak jak na razie wszystko jest w porządku. Nie żeby piszący te słowa Skrypciarz narzekał. Zamiast zapłacić kilka tysięcy dolarów, zapłacił 124,25 USD: 123 USD za robociznę i 1,25 USD za części.

Prosta matematyka, to lepsze niż wydanie 2 czy 3 tysięcy.

Chyba nie ma sensu podkreślać, że piszący te słowa Skrypciarz bardzo chciał uczcić swoje szczęście. A w jaki inny sposób lepiej uczcić coś takiego, niż pisząc skrypt, który zmieni mapowanie dysków sieciowych tak, żeby wskazywały na adres IP zdalnego komputera, a nie nazwę komputera:

On Error Resume Next



Set objNetwork = CreateObject("Wscript.Network")

Set colDrives = objNetwork.EnumNetworkDrives



For i = 0 to colDrives.Count-1 Step 2

    strDriveLetter = colDrives.Item(i)

    strNetworkPath = colDrives.Item(i + 1)



    strNetworkPath = Replace(strNetworkPath, "\\", "")

    arrPath = Split(strNetworkPath, "\")



    strComputerName = arrPath(0)

    strFolderName = arrPath(1)



    Set objWMIService = GetObject("winmgmts:\\" & strComputerName & "\root\cimv2")



    Set colItems = objWMIService.ExecQuery _

        ("Select * From Win32_NetworkAdapterConfiguration Where IPEnabled = True")



    For Each objItem in colItems

        For Each objAddress in objItem.IPAddress

            strIPAddress = objAddress

        Next

    Next



    objNetwork.RemoveNetworkDrive strDriveLetter



    Wscript.Sleep 3000



    strNewPath = "\\" & strIPAddress & "\" & strFolderName

    objNetwork.MapNetworkDrive strDriveLetter, strNewPath

Next
Uwaga: Jeżeli macie na swoim komputerze zainstalowany system operacyjny Windows Vista, potrzebujecie pełnych uprawnień, żeby skrypt działał poprawnie. Otwieramy wiersz poleceń, klikając prawym klawiszem myszy i wybieramy opcję Run As Administrator, a następnie uruchamiamy skrypt z wiersza polecenia.

Zobaczmy, jak ten skrypt działa. Na początek powinniśmy zauważyć, że rozpoczęliśmy od zdania On Error Resume Next. Zazwyczaj nie robimy tego w naszej rubryce; z reguły pomijamy kwestię błędów, żeby nasze skrypty nie były zbyt długie i żeby uczynić je odrobinę łatwiejszymi w odbiorze. W tym przypadku jednak niekiedy napotykaliśmy na dziwne błędy podczas wywoływania metody RemoveNetworkDrive, które powodowały anomalie w działaniu skryptu. Skąd wynikały te problemy? No cóż, prawdę mówiąc nie jesteśmy pewni. Ale dodanie zdania On Error Resume Next wydaje się rozwiązywać cały problem, więc po co drążyć kwestię…

Zakładamy także, że to wymiana bezpiecznika rozwiązała problem z samochodem piszącego te słowa Skrypciarza.

Jeżeli chodzi o prawdziwy kod, naszym następnym posunięciem będzie utworzenie wystąpienia obiektu Wscript.Network i zastosowanie poniższego wiersza w celu zwrócenia kolekcji wszystkich zmapowanych dysków sieciowych na komputerze:

Set colDrives = objNetwork.EnumNetworkDrives

Metoda EnumNetworkDrives w perfekcyjny sposób zwraca wszystkie zmapowane dyski na komputerze. Jednak robi to w nieco dziwaczny sposób: zwrócone informacje powracają jako kolekcja wyglądająca następująco:

X:

\\atl-fs-01\public

Y:

\\atl-fs-01\users

Z:

\\atl-fs-01\scripts

Jak widzimy, każdy zmapowany dysk obejmuje dwa elementy w kolekcji, pierwszy (np. X:) reprezentujący literę dysku, oraz drugi (\\atl-fs-01\public), reprezentujący ścieżkę sieciową. Dlatego też nasza pętla For Next, której użyjemy do przejścia przez kolekcję, wygląda nieco dziwnie:

For i = 0 to colDrives.Count-1 Step 2

Jak widzimy, uruchamiamy pętlę ze zmienną licznika o wartości i równej 0, a to dlatego, że pierwszy element w każdej tablicy lub kolekcji zawsze ma numer 0. Kończymy działanie pętli, kiedy dojdziemy do liczby elementów w kolekcji (Count) minus 1. Dlaczego minus 1? Ponieważ ostatni element w kolekcji to będzie ścieżka sieciowa; dla celów naszej pętli chodzi nam jedynie o literę dysku. Z tego samego powodu dodaliśmy parametr Step 2, co powoduje, że uwzględniamy co drugi element w kolekcji. W ten sposób pobieramy tylko litery dysków – X:, Y:, Z: – i unikamy problemu pobrania tego samego dysku dwukrotnie (najpierw przy użyciu litery dysku, a potem jeszcze raz za pomocą ścieżki sieciowej.

Wewnątrz pętli zaczynamy od przypisania litery dysku do zmiennej o nazwie strDriveLetter:

strDriveLetter = colDrives.Item(i)

Następnie stosujemy poniższy wiersz kodu w celu przypisania ścieżki sieciowej do zmiennej o nazwie strNetworkPath:

strNetworkPath = colDrives.Item(i + 1)

Zwróćmy uwagę na wskaźnik, który tutaj zastosowaliśmy: i + 1. Zastosowaliśmy go dlatego, że ścieżka sieciowa skojarzona z określoną literą dysku zawsze będzie miała wskaźnik o 1 większy niż litera dysku. Jeżeli dysk Y: ma wskaźnik 2, to ścieżka \\atl-fs-01\users będzie miała wskaźnik 3.

Trochę to dziwne, ale właśnie tak to działa.

Oczywiście Skrypciarze wiedzą o tym, że aby zmapować dysk używając adresu IP komputera, przydaje się znajomość tego numeru. Jednym ze sposobów na określenie adresu IP komputera jest zastosowanie klasy Win32_NetworkAdapterConfiguration. Zanim jednak będziemy mogli ją zastosować, musimy przeprowadzić analizę nazwy komputera na podstawie ścieżki sieciowej. Do tego posłuży nam poniższy fragment kodu:

strNetworkPath = Replace(strNetworkPath, "\\", "")

arrPath = Split(strNetworkPath, "\")



strComputerName = arrPath(0)

strFolderName = arrPath(1)

Zobaczmy, czy potrafimy wytłumaczyć, o co w tym chodzi. Na początek stosujemy funkcję skryptu VBScript w celu zastąpienia każdego wystąpienia \\ … niczym. Dzięki temu, ścieżka sieciowa \\atl-fs-01\public zamieni się w coś takiego:

  • atl-fs-01\public

Teraz zastosujemy funkcję Split i rozdzielimy tę wartość używając znaku „\” jako delimitera. W wyniku tego otrzymamy tablicę o nazwie arrPath składającą się z następujących dwóch elementów:

  • atl-fs-01
  • public

Następnie przypisujemy element 0 (atl-fs-01) do zmiennej o nazwie strComputerName, a potem przypisujemy element 1 (public) do zmiennej o nazwie strFolderName. Wiemy teraz dwie rzeczy: jaka jest nazwa komputera na którym znajduje się zmapowany folder oraz jaka jest nazwa tego folderu.

Zaraz, zaraz. Jak się okazuje, wiemy trzy rzeczy: wiemy także, że mamy teraz wystarczająco dużo informacji, żeby połączyć się ze zdalnym komputerem atl-fs-01 w celu określenia adresu IP. Zrobimy to używając następującego fragmentu kodu:

Set objWMIService = GetObject("winmgmts:\\" & strComputerName & "\root\cimv2")



Set colItems = objWMIService.ExecQuery _

    ("Select * From Win32_NetworkAdapterConfiguration Where IPEnabled = True")

Teraz podłączamy się jedynie do usługi WMI na zdalnym komputerze, następnie wyszukujemy kolekcję kart sieciowych (używając klasy Win32_NetworkAdapterConfiguration). Zwróćmy uwagę na zdanie Where zawarte w naszej kwerendzie:

Where IPEnabled = True

Jeżeli wysyłamy kwerendę do klasy Win32_NetworkAdapterConfiguration bez zastosowania zdania Where, prawdopodobnie otrzymamy 10 lub więcej kart sieciowych; najprawdopodobniej większość z nich to będą wirtualne karty sieciowe, czyli takie, które nie są powiązane z żadnym fizycznym sprzętem i nie mają adresu IP. Ograniczając liczbę pobieranych kart sieciowych do kart mających właściwość IPEnabled o wartości True, uzyskamy jedynie karty sieciowe, które naprawdę mają adres IP:

For Each objItem in colItems

    For Each objAddress in objItem.IPAddress

        strIPAddress = objAddress

    Next

Next

Jak się okazuje, karta sieciowa może mieć więcej niż jeden adres IP; z tego powodu, właściwość IPAddress zachowuje wartości w formie tablicy. To z kolei oznacza, że musimy zastosować pętlę For Each w celu dostania się do tych wartości. Poniższy fragment kodu uruchamia pętlę przechodzącą przez pobrany zbiór kart sieciowych posiadających adres IP, która następnie w przypadku każdej karty sieciowej przechodzi przez przypisane do niej adresy IP. Nie mamy pojęcia, który adres IP jest „najlepszy”, więc wybieramy po prostu ostatni adres, jaki znajdziemy i przypisujemy go do zmiennej o nazwie strIPAddress:

strIPAddress = objAddress

W końcu jesteśmy gotowi do zmiany mapowania naszego pierwszego dysku sieciowego. Z wyjątkiem jednej rzeczy: nie istnieje metoda typu RemapNetworkDrives. Zamiast tego musimy odłączyć istniejący dysk (zmapowany przy pomocy nazwy komputera), a następnie utworzyć nowy dysk sieciowy (o tej samej literze dysku), który zostanie zmapowany przy użyciu adresu IP. Jak się za to zabrać? Najpierw odłączamy istniejący dysk:

objNetwork.RemoveNetworkDrive strDriveLetter

Następnie używamy metody Sleep i zatrzymujemy skrypt na 3 sekundy (3 000 milisekund); to pomoże nam się upewnić, że istniejący dysk naprawdę został odłączony, zanim spróbujemy zmapować nowy dysk do danej litery dysku. Po krótkiej przerwie tworzymy nową ścieżkę sieciową, w której stosujemy adres IP (strIPAddress) zamiast nazwy komputera:

strNewPath = "\\" & strIPAddress & "\" & strFolderName

Kiedy już mamy ścieżkę sieciową, wywołujemy metodę MapNetworkDrive i mapujemy dysk do adresu IP:

objNetwork.MapNetworkDrive strDriveLetter, strNewPath

W ten sposób dysk X:, który kiedyś był zmapowany do \\atl-fs-01\public, zostaje przemapowany do adresu IP (np., \\192.168.1.1\public). Następnie kontynuujemy działanie pętli i powtarzamy ten proces dla następnego zmapowanego dysku.

Skoro problem piszącego te słowa Skrypciarza z samochodem został rozwiązany, to czy to oznacza, że 2 000 USD może przeznaczyć na czekoladki? Oczywiście, że nie. Skąd taki pomysł. Samochód Skrypciarza spisuje się co prawda bez zarzutu, ale Skrypciarz z jakichś przyczyn ma wątpliwości, czy na pewno wymiana bezpiecznika ma coś wspólnego z naprawą i rozwiązuje ten problem na amen.

 Do początku strony Do początku strony

Centrum skryptów - Systemy operacyjne