При составлении сценариев WMI или ADSI иногда требуется перебрать все компьютеры указанного домена (или компьютеры по какому-то списку), чтобы произвести над каждым компьютером некоторые действия. При этом, если очередной компьютер не существует или просто выключен, попытка подключения к нему (с помощью WMI-моникера или строки ADsPath) будет производиться достаточно долго, что резко снижает производительность сценария. Чтобы несколько компенсировать потерю производительности в этом случае, можно использовать команду ping для проверки существования компьютера (команда ping работает быстрее, чем подключение по WMI или ADSI). Для этого перед попыткой подключения в сценарии вы можете вызвать следующую функцию, которая вернёт True или False, в зависимости от того, отвечает компьютер, или нет (функция получает имя компьютера или IP-адрес для проверки):
'Функция Alive() получает имя компьютера в локальной сети (или ip-адрес) и 'возвращает True, если компьютер пингуется, и False в противном случае Function Alive(ByVal strHost) Const SYSTEM_FOLDER = 1, TEMP_FOLDER = 2 ' константы FileSystemObject Set objFSO = CreateObject("Scripting.FileSystemObject") With objFSO Do 'генерация пути к временному файлу: КаталогВременныхФайлов\ИмяВременногоФайла strTempFile = .BuildPath(.GetSpecialFolder(TEMP_FOLDER), .GetTempName) 'если такой файл существует, продолжаем попытки генерации пути: Loop While .FileExists(strTempFile) 'составим командную строку вызова ping с перенаправлением во временный файл 'cmd.exe завершить после исполнения (параметр /c) 'число запросов для ping - один (параметр -n 1) strCmdLine = .BuildPath(.GetSpecialFolder(SYSTEM_FOLDER), "cmd.exe") _ & " /c " & .BuildPath(.GetSpecialFolder(SYSTEM_FOLDER), "ping.exe") _ & " -n 1 " & strHost & " > " & strTempFile End With 'запускаем ping синхронно, в скрытом окне CreateObject("Wscript.Shell").Run strCmdLine, 0, True 'паттерн регулярного выражения для анализа вывода ping Set objRE = CreateObject("VBScript.RegExp") 'маска _XXX.XXX.XXX.XXX:_, где "X" - любое число, причём в каждой группе может быть 'от 1 до 3 цифр, а "_" - пробел (т.е. паттерн соответствует любому валидному IP-адресу, 'который может появиться в выводе команды ping) 'предполагается, что если в выводе ping будет присутствовать какой-то IP-адрес, это 'будет означать, что ping прошёл успешно, иначе - что удалённый компьютер не отвечает; 'примечание: при неудачном ping'е в выводе команды в принципе может присутствовать 'IP-адрес, но чаще всего он не будет содержать двоеточия и пробела в конце; 'для верности необходимо проверить также наличие строки "TTL=" в выводе objRE.Pattern = " [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}: [\s\S]*TTL=" 'открытие временного файла, содержащего вывод команды ping Set objTS = objFSO.OpenTextFile(strTempFile, 1) 'функция возвращает результат проверки паттерна Alive = objRE.Test(objTS.ReadAll) 'закрытие и удаление временного файла objTS.Close objFSO.DeleteFile strTempFile End Function
Другой пример определения существования компьютера, с помощью самого же WMI (автор примера — Алексей Жучков, г. Ессентуки):
Function Avaible(name) 'пингом проверяет доступность компьютера name в сети On Error Resume Next Set objPing = GetObject("winmgmts:{impersonationLevel=impersonate}")._ ExecQuery("select * from Win32_PingStatus where address = '"_ & name & "'") For Each objStatus in objPing If IsNull(objStatus.StatusCode) Or objStatus.StatusCode 0 Then Avaible = False Else Avaible = True End If Next End function ' примеры вызова WScript.Echo Avaible("Vasya") WScript.Echo Avaible("192.168.0.1")
Ниже размещён класс, предназначенный как для проверки существования компьютера (ping), так и для проверки состояния указанных служб не нём. При необходимости указанную службу можно запустить / остановить. Класс любезно предоставлен Васильевым Григорием © 2005г.:
' ************************************************************************************************* ' Класс Server ' Используется для проверки работоспособности сервера. ' Использование: ' set srv=new Server - создание экземпляра класса ' srv.Connect - Процедура подключение к серверу. ' (После этого становятся доступными свойства: ' srv.Name - Имя подключенного сервера ' srv.Allive - {true,false} - прошел ли пинг сервера при подключении или последнем вызове ' функции Ping. ' Функции: ' Ping() - возвращаемое значение: {true,false} - Проверка доступности (Ping) сервера ' CheckService(SrvsName,NeedStatus,RunIT) - Функция проверки статуса служб. ' Параметры: ' SrvsName - Имя службы. ' NeedStatus - Строки {"running" или "stopped"} - Нужный статус службы. ' RunIT - Булево - Если Истина - то функция приведет службу в нужный статус ' (Если running - то запустит), в противном случае ничего делаться не будет. ' Возвращаемые значения: ' 1 - Установлен новый статус службы. (При RunIT=true) ' 0 - Статус службы совпадает с нужным статусом. ' -1 - Статус службы НЕ СОВПАДАЕТ с нужным статусом. ' (Если был указан параметр RunIT=true - это значит что запуск службы не удался.) ' Ошибки: ' -200 - Не установлено соединение с сервером ' -100 - Не правильные параметры функции ' ************************************************************************************************* ' © 2005 Васильев Григорий ' Если у вас есть идея (а лучше реализация), того как можно эту программу улучшить - ' просьба поделиться вашими мыслями с помощью элетронного средства связи (E-Mail): ' Dead_Angelbk.ru ' ************************************************************************************************* Class Server Private ST_SrvName Private BOOL_PingStatus Private Sub Class_Initialize() ST_SrvName="" BOOL_PingStatus=false End Sub Public Sub Connect(srvName) ST_SrvName=srvName Ping End Sub Public Property Get Name Name=ST_SrvName End Property Public Property Get Allive Allive=BOOL_PingStatus End Property Public Function CheckService(SrvsName,NeedStatus,RunIT) if ST_SrvName="" Then CheckService=-200 Exit Function End If if (SrvsName="") OR ((LCase(NeedStatus)"stopped") AND (LCase(NeedStatus)"running")) then CheckService=-100 Exit Function End If Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & ST_SrvName & _ "\root\cimv2") Set colListOfServices = objWMIService.ExecQuery("Select * from Win32_Service WHERE Name=""" & _ Trim(SrvsName) & """") if colListOfServices.Count " & strTempFile End With CreateObject("Wscript.Shell").Run strCmdLine, 0, True Set objRE = CreateObject("VBScript.RegExp") objRE.Pattern = " [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}: [\s\S]*TTL=" Set objTS = objFSO.OpenTextFile(strTempFile, 1) Ping = objRE.Test(objTS.ReadAll) objTS.Close objFSO.DeleteFile strTempFile BOOL_PingStatus = true End Function End Class 'ПРИМЕР ИСПОЛЬЗОВАНИЯ КЛАССА: set Xmyclass = new Server 'создаём экземпляр класса Xmyclass.Connect ("terminal") 'подключаемся к компьютеру "terminal" Msgbox Xmyclass.Name 'получаем имя компьютера Msgbox Xmyclass.Allive 'узнаём, прошёл ли пинг при подключении Msgbox Xmyclass.Ping 'пингуем ещё раз, получаем результат 'проверяем, запущена ли служба "SQLSERVERAGENT": Msgbox Xmyclass.CheckService("SQLSERVERAGENT","Running", false)
Источник: http://www.script-coding.info