В предыдущей статье мы взяли наш сценарий под названием ChangeIPAddress.vbs, разработанный нами ранее, и изменили его так, чтобы он мог изменять IP адрес на удаленном компьютере. Ниже можно увидеть, как выглядит наш модифицированный сценарий:
Option Explicit
Dim objWMIService
Dim objNetAdapter
Dim strComputer
Dim strAddress
Dim arrIPAddress
Dim arrSubnetMask
Dim colNetAdapters
Dim errEnableStatic
If WScript.Arguments.Count = 0 Then
Wscript.Echo "Usage: ChangeIPAddress.vbs new_IP_address"
WScript.Quit
End If
strComputer = "xp2"
strAddress = Wscript.Arguments.Item(0)
arrIPAddress = Array(strAddress)
arrSubnetMask = Array("255.255.255.0")
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colNetAdapters = objWMIService.ExecQuery("Select * from Win32_NetworkAdapterConfiguration where IPEnabled=TRUE")
For Each objNetAdapter in colNetAdapters
errEnableStatic = objNetAdapter.EnableStatic(arrIPAddress, arrSubnetMask)
Next
Строка:
говорит нам, что имя компьютера, для которого будет выполнен сценарий, XP2. Удаленный компьютер XP2 изначально имел IP адрес 172.16.11.43.
Теперь, когда мы запустили этот сценарий, набрав команду ChangeIPAddress.vbs 172.16.11.65 с рабочей станции администратора под названием XP, произошло следующее:
Что нам делать с результатами?
Первое, что мы можем сделать, это сказать: «Ну ладно, раз уж это все работает, то давайте просто проигнорируем ошибку». Необходимо кое-что сказать по поводу такого подхода. В конце концов, любой настоящий администратор знает, что информационные технологии (IT) – это не точная наука, и они часто используют обходные пути для решения проблем, если им не удается найти правильное решение.
Так как же мы может игнорировать ошибку? Просто добавьте следующую строку перед секцией с заголовком:
Другими словами, наш заголовочный раздел будет теперь выглядеть так:
Option Explicit
On Error Resume Next
Dim objWMIService
etc.
Теперь ошибка не появляется, и наш сценарий работает, как и ранее. Но на его выполнение по-прежнему уходит достаточно долго времени. Что происходит?
Сообщения об ошибках иногда выглядят так, как будто они зашифрованы, и это одна из них. Давайте посмотрим на него снова:
А ниже приведена строка в коде, которая приводит к появлению ошибки:
Теперь эта строка в коде работает (т.е. IP адрес на нужном компьютере изменяется), но все равно возникает ошибка. Почему?
Давайте попробуем понять, что представляет собой объект SWebObjectEx. Быстрый поиск в MSDN приводит нас к этой странице, из которой мы узнаем следующее:
Extends the functionality of SWbemObject. This object adds the Refresh method for SWbemRefresher objects. (Расширяет функциональность объекта. Этот объект добавляет метод Refresh для объектов SWbemRefresher).
Хорошо, объект SWbemObjectEx просто расширяет функциональность объекта SWbemObject. А для чего нужен объект SWbemObject?
Contains and manipulates a single WMI object class or instance. (Содержит и управляет одним объектом класса WMI или ссылкой на него)
Хорошо, а что же это значит? Из этой страницы мы можем узнать гораздо больше, он она словно написана на латыни. Если попытаться перевести, что там написано, объект SWbemObject (а поэтому и объект SWbemObjectEx) – это что-то, чем вы управляете или запрашиваете в WMI. В нашем сценарии вы запрашиваете класс Win32_NetworkAdapterConfiguration, и получаете набор объектов под названием colNetAdapters, которые представляют собой сетевые адаптеры (network adapters) на компьютере. Поэтому объект SWbemObjectEx (или SWbemObject), который упоминается в сообщении об ошибке, представляет собой сам сетевой адаптер objNetAdapter.
Итак, объект objNetAdapter формирует ошибку. Почему?
Я должен поговорить с некоторыми своими друзьями, которые являются гуру в области написания сценариев, чтобы попытаться выяснить эту проблему. И лучший ответ, который я получил, не был исчерпывающим, но он все же помог мне разобраться, в чем дело.
В любом случае, вот, что могло стать проблемой. Согласно ответу одного из этих гуру, кажется, что после установки некоторых обновлений к операционной системе Windows XP что-то поменялось в том, каким образом создается ответный вызов, если выполняется предложение, которое содержит ошибку. Обычно, если вызов метода EnableStatic объекта класса Win32_NetworkAdapterConfiguration, для которого было присвоено значение, завершается успешно, то он возвращает 0, что означает, что не было ошибок, или же он возвращает 1, что значит, что требуется перезагрузка (смотрите эту страницу для возвращаемого значения). Конечно, для операционной системы Windows XP не требуется перезагрузка, если вы меняете IP адрес сетевого адаптера (network adapter). Если, по каким-либо причинам обновление что-то изменило у поставщика WMI provider или какой то скрытый элемент, и операционная система Windows думает, что требуется перезагрузка перед тем, как новый адрес будет установлен для требуемого компьютера, то в результате этого формируется ошибка, т.к. конфигурация сетевого адаптера (network adapter configuration) на компьютере остается в неопределенном состоянии до тех пор, пока компьютер не будет перезагружен. Но т.к. сценарий по-прежнему запущен на рабочей станции администратора, когда конфигурация сетевого адаптера на требуемом компьютере находится в неопределенном состоянии, то соединение RPC между двумя компьютерами разрывается до того, как сценарий может завершить работу. Отсюда возникает ошибка.
Это наилучший ответ, который у меня есть для решения этой проблемы на сегодняшний день, но я продолжаю свое расследование. А тем временем давайте посмотрим, можем ли мы как-нибудь изолировать эту проблему, т.е. эта ошибка связана только с методом EnableStatic класса Win32_NetworkAdapterConfiguration, а не с чем-то более общим. Что, если мы попытаемся написать другой сценарий, который делает что-нибудь другое с сетевым адаптером (network adapter) на выбранной машине вместо того, чтобы изменять его IP адрес? Например, как насчет того, чтобы попытаться изменить шлюз по умолчанию (default gateway) вместо IP адреса на выбранной машине? Если это сработает, то, по крайней мере, мы сможем успешно подключиться с нашей рабочей станции администратора к удаленной машине и вызвать метод WMI для изменения сетевых настроек на ней.
С этого момента я бы хотел предположить, что вы остановились на чтении этой статьи и вернулись к четвертой части этой статьи, в которой я показал вам, как использовать MSDN, чтобы узнать, как использовать свойства и методы класса Win32_NetworkAdapterConfiguration class. Я готов поспорить, что с его помощью вы самостоятельно сможете написать сценарий. Попробуйте!
INTERMISSION (перерыв)
Хорошо, теперь вы попробовали написать ваш собственный сценарий, и может быть он даже работает, а может быть и нет. Если он не работает, то выполните следующие действия:
Это должно быть то, что нам нужно, поэтому нажмите на методе SetGateways, в результате чего откроется страница SetGateways Method of the Win32_NetworkAdapterConfiguration Class page.
Итак, мы узнали, что наш компьютер, для которого мы хотим запустить сценарий, должен иметь статический адрес перед тем, как мы сможем применить для него наш сценарий. Читая дальше, вы узнаете, что синтаксис вызова этого метода выглядит так:
Здесь A – это строковая переменная, содержащая IP адрес для шлюза (gateway), а B – это целое значение от 1 до 9999, задающее метрику (metric).
Теперь у вас достаточно информации для того, чтобы написать ваш сценарий. Самый простой способ для этого, это начать с вашего оригинального сценария под названием ChangeIPAddress.vbs, который можно найти во второй части этой статьи и изменить его таким образом, пока мы не получим новый сценарий, который будет выглядеть так (и который мы назовем ChangeGateway.vbs):
'=========================
' NAME: ChangeGateway.vbs
'
'AUTHOR: Mitch Tulloch
'DATE: February 2007
'
'ARGUMENTS:
'1. gateway_address
'2. metric
'=========================-
Option Explicit
Dim objWMIService
Dim objNetAdapter
Dim strComputer
Dim strGateway
Dim arrGateway
Dim intMetric
Dim arrMetric
Dim colNetAdapters
Dim errGateway
'Check for missing arguments
If WScript.Arguments.Count = 0 Then
Wscript.Echo "Usage: ChangeGateway.vbs gateway_address metric"
WScript.Quit
End If
strComputer = "xp2"
strGateway = Wscript.Arguments.Item(0)
arrGateway = Array(strGateway)
intMetric = Wscript.Arguments.Item(1)
arrMetric = Array(intMetric)
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colNetAdapters = objWMIService.ExecQuery("Select * from Win32_NetworkAdapterConfiguration where IPEnabled=TRUE")
For Each objNetAdapter in colNetAdapters
errGateway = objNetAdapter.SetGateways(arrGateway, arrMetric)
Next
'Display result or error code
If errGateway=0 Then
Wscript.Echo "Adapter's gateway has been successfully changed to " & strGateway
Else
Wscript.Echo "Changing the adapter's gateway was not successful. Error code " & errGateway
End If
Скопируйте этот сценарий в блокнот (Notepad) (при этом необходимо отключить перенос строк) и сохраните его под именем ChangeGateway.vbs. Теперь давайте его проверим. Давайте зайдем на удаленную машину XP2, и откроем командную строку (сommand prompt) и наберем команду ipconfig /all в результате чего получим следующее:
C:\>ipconfig /all
Windows IP Configuration
Host Name . . . . . . . . . . . . : XP2
Primary Dns Suffix . . . . . . . : contoso.com
Node Type . . . . . . . . . . . . : Unknown
IP Routing Enabled. . . . . . . . : No
WINS Proxy Enabled. . . . . . . . : No
Ethernet adapter Local Area Connection:
Connection-specific DNS Suffix . :
Description . . . . . . . . . . . : Intel 21140-Based PCI Fast Ethernet
Adapter (Generic)
Physical Address. . . . . . . . . : 00-03-FF-21-88-8C
Dhcp Enabled. . . . . . . . . . . : No
IP Address. . . . . . . . . . . . : 172.16.11.80
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 172.16.11.1
C:\>
Теперь на рабочей станции администратора XP, давайте откроем командную строку (command prompt) и запустим сценарий таким образом:
C:\tools>ChangeGateway.vbs 172.16.11.2 5
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
Adapter's gateway has been successfully changed to 172.16.11.2
C:\tools>
Сценарию потребуется на выполнение 5 секунд, и не появится никаких ошибок. (Обратите внимание, что убрал строку On Error Resume Next из заголовка своего сценария, т.к. я хочу увидеть ошибки, в случае их появления).
Теперь давайте вернемся на удаленную машину XP2 и снова наберем команду ipconfig /all:
C:\>ipconfig /all
Windows IP Configuration
Host Name . . . . . . . . . . . . : XP2
Primary Dns Suffix . . . . . . . : contoso.com
Node Type . . . . . . . . . . . . : Unknown
IP Routing Enabled. . . . . . . . : No
WINS Proxy Enabled. . . . . . . . : No
Ethernet adapter Local Area Connection:
Connection-specific DNS Suffix . :
Description . . . . . . . . . . . : Intel 21140-Based PCI Fast Ethernet
Adapter (Generic)
Physical Address. . . . . . . . . : 00-03-FF-21-88-8C
Dhcp Enabled. . . . . . . . . . . : No
IP Address. . . . . . . . . . . . : 172.16.11.80
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 172.16.11.2
C:\>
Это сработало. Нет ошибок, ничего загадочного—мы удаленно запустили сценарий, который выполнился на другом компьютере и изменил на нем шлюз по умолчанию (default gateway).
Хорошо, мы не проверили изменилось ли значение метрики, не так ли? Команда ipconfig не позволяет нам получить эту информацию, но мы можем использовать команду netsh:
C:\>netsh interface ip show address
Configuration for interface "Local Area Connection"
DHCP enabled: No
IP Address: 172.16.11.80
SubnetMask: 255.255.255.0
Default Gateway: 172.16.11.2
GatewayMetric: 5
InterfaceMetric: 0
C:\>
Удивительно, но это работает.
Tags: dns, proxy, redirect, Windows XP