Перейти на главную страничку сайта (список статей, файлы для скачивания)

ФОРУМ (здесь можно обсудить эту статью, а также любые проблемы программирования на различных макроязыках и в скриптовых средах)

Рецепты Windows Scripting: определение существования компьютера и состояния служб

При составлении сценариев 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_Angel<собака!>bk.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<1 then
        CheckService=-1
    End If
    For Each objService in colListOfServices
            if LCase(objService.State)=LCase(NeedStatus) then
                CheckService=0
            Else
                if RunIT=false Then
                    CheckService=-1
                    Exit Function
                End If
                Select Case LCase(NeedStatus)
                    Case "stopped"
                        ErrReturn = objService.StopService()
                    Case "running"
                        ErrReturn = objService.StartService()
                    Case else
                        CheckService=-100
                        Exit Function
                End Select
                if ErrReturn<>0 Then
                    CheckService=-1
                Else
                    CheckService=1
                End If
            End If
    Next
End Function

Public Function Ping()
    strHost = Name
    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)
        strCmdLine = .BuildPath(.GetSpecialFolder(SYSTEM_FOLDER), "cmd.exe") _
            & " /c " & .BuildPath(.GetSpecialFolder(SYSTEM_FOLDER), "ping.exe") _
            & " -n 1 " & strHost & " > " & 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)

Людоговский Александр

Перейти на главную страничку сайта (список статей, файлы для скачивания)

© 2007 http://www.script-coding.com При любом использовании материалов сайта обязательна ссылка на него как на источник информации, а также сохранение целостности и авторства материалов.