Показать полную графическую версию : [решено] Помогите наваять скрипт? Поиск строки в файле.
Iska, Боюсь, что для меня это крутовато, не осилил. Пожалуй сделаю как-то так:
on error resume next
затем если (пинг прошел)&(была запись в файл) то NoSNMP=False
иначе NoSnmp=True
если NoSNMP то пишем в файл ИП-адрес "плохого" устройства
Только пока не разобрался с переходами по on error resume next
Трудно без нормального отладчика с контрольными точками и пошаговым выполнением команд (((
Покритикуйте алгоритм.
Прошу помощи в реализации на vbs.
Покажите Ваш текущий код (не забывайте обрамлять его тэгом «code»).
Iska, Вот
'=============================================================================
' Процедура асинхронной обработки экземпляра объекта (замечание: в данном конкретном случае
' будет возвращаться единственный объект, однако, в большинстве случаев запросы
' возвращают множество объектов)
Sub Sink_OnObjectReady(objWbemObject, objWbemAsyncContext)
Dim strComputer
strComputer = objWbemAsyncContext.Item("HostName")
If Not IsNull(objWbemObject.StatusCode) Then
If objWbemObject.StatusCode = 0 Then
objWmiNamedValueSet.Add "AgentAddress", strComputer
objWmiNamedValueSet.Add "AgentReadCommunityName", "poll"
on error resume next
Set colSystem = objWmiServices.InstancesOf("SNMP_RFC1213_MIB_system", , objWmiNamedValueSet)
For Each objSystem In colSystem
'На предыдущей строке выдает error, если устройство не умеет SNMP.
If (Right(objSystem.sysName,12)="123456789012") Then
objSystem.sysName=Left(objSystem.sysName,Len(objSystem.sysName)-12) + ".m"
Else
objSystem.sysName=objSystem.sysName + ".m"
End If
NFile1.WriteLine objSystem.sysName + " IN A " + strComputer
Next
End If
End If
End Sub
Нужно - если устройство не умеет SNMP, то записать его ИП-адрес в файл.
Другими словами - прошел пинг и прошла запись
"NFile1.WriteLine objSystem.sysName + " IN A " + strComputer"
то оно умеет, иначе пишем его ИП-адрес в файл для дальнейшего анализа.
glukin, это только одна процедура. Я имел в виду — весь код.
Iska, ок
File_Out1 = "D:\SNMP.txt"
File_Out2 = "D:\30.10.txt"
File_out3 = "D:\31.10.txt"
File_Date = "D:\date.txt"
File_NoSNMP = "D:\NoSNMP.txt"
Set objWmiLocator = CreateObject("WbemScripting.SWbemLocator")
Set objWmiServices = objWmiLocator.ConnectServer("", "root\snmp\localhost")
Set objWmiNamedValueSet = CreateObject("WbemScripting.SWbemNamedValueSet")
Set FSO = CreateObject("Scripting.FileSystemObject")
Set NFile1 = FSO.OpenTextFile(File_Out1, 2, True)
Set NFile2 = FSO.OpenTextFile(File_Out2, 2, True)
Set NFile3 = FSO.OpenTextFile(File_Out3, 2, True)
Set DateFile = FSO.OpenTextFile(File_Date, 2, True)
Set NoSNMP = FSO.OpenTextFile(File_NoSNMP, 2, True)
'Option Explicit
Dim arrComputers(255)
k = 0
For i = 115 To 115
For j = 0 To 255
arrComputers(k) = "10.31." + CStr(i) + "." + CStr(j)
k = k + 1
Next
Next
Dim strComputer
Dim objSWbemServicesEx
Dim objSWbemSink
Dim objSWbemNamedValueSet
Dim lngCount
Dim lngQueueCurrLength, lngQueueMaxLength
Dim i
' Максимальная длина очереди (в данном примере — сколько машин будут пинговаться одновременно),
' выбирается произвольно
lngQueueMaxLength = 10
' Текущая длина очереди
lngQueueCurrLength = 0
lngCount = UBound(arrComputers)
i = 0
Set objSWbemServicesEx = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\Root\CIMV2")
Set objSWbemSink = WScript.CreateObject("WbemScripting.SWbemSink", "Sink_")
While (i <= lngCount) Or (lngQueueCurrLength > 0) ' Пингуем пока не кончатся компы и очередь
If (i <= lngCount) And (lngQueueCurrLength < lngQueueMaxLength) Then
' В коллекции «objSWbemNamedValueSet» будем передавать адрес/имя хоста (замечание: в данном конкретном случае
' сие, в принципе, необязательно, поскольку класс Win32_PingStatus и так содержит
' свойство «.Address», но тут показана сама технология передачи данных в процедуру асинхронной обработки)
Set objSWbemNamedValueSet = WScript.CreateObject("WbemScripting.SWbemNamedValueSet")
objSWbemNamedValueSet.Add "HostName", arrComputers(i)
' Все запросы будут обрабатываться в единственной процедуре обработки
objSWbemServicesEx.ExecQueryAsync objSWbemSink, "SELECT * FROM Win32_PingStatus WHERE ADDRESS = '" & arrComputers(i) & "'", , , , objSWbemNamedValueSet
i = i + 1
lngQueueCurrLength = lngQueueCurrLength + 1
Else
' Ожидаем, пока не будут обработаны все асинхронные запросы
WScript.Sleep 100
End If
Wend
objSWbemSink.Cancel
Set objSWbemSink = Nothing
Set objSWbemServicesEx = Nothing
NFile1.Close
NFile2.Close
NFile3.Close
NoSNMP.Close
DateFile.Close
WScript.Quit 0
'=============================================================================
'=============================================================================
' Процедура асинхронной обработки экземпляра объекта (замечание: в данном конкретном случае
' будет возвращаться единственный объект, однако, в большинстве случаев запросы
' возвращают множество объектов)
Sub Sink_OnObjectReady(objWbemObject, objWbemAsyncContext)
Dim strComputer
strComputer = objWbemAsyncContext.Item("HostName")
If Not IsNull(objWbemObject.StatusCode) Then
If objWbemObject.StatusCode = 0 Then
objWmiNamedValueSet.Add "AgentAddress", strComputer
objWmiNamedValueSet.Add "AgentReadCommunityName", "poll"
on error resume next
Set colSystem = objWmiServices.InstancesOf("SNMP_RFC1213_MIB_system", , objWmiNamedValueSet)
For Each objSystem In colSystem
If (Right(objSystem.sysName,12)=".123456789012") Then
objSystem.sysName=Left(objSystem.sysName,Len(objSystem.sysName)-12) + ".m"
Else
objSystem.sysName=objSystem.sysName + ".m"
End If
NFile1.WriteLine objSystem.sysName + " IN A " + strComputer
Next
End If
End If
End Sub
'=============================================================================
'=============================================================================
' Процедура, вызываемая при завершении асинхронной обработки
Sub Sink_OnCompleted(iHResult, objWbemErrorObject, objWbemAsyncContext)
objWbemAsyncContext.DeleteAll
Set objWbemAsyncContext = Nothing
' Уменьшаем длину очереди
lngQueueCurrLength = lngQueueCurrLength - 1
'lngCount = lngCount - 1
End Sub
Тяжёлый код. Используйте Option Explicit в начале кода, препятствует появлению многих глупых ошибок с описками в именовании переменных.
Попробуйте так (добавить всё ту же функцию):
Function ClassExists(objSWbemServicesEx, strClassName)
Dim objSWbemObjectEx
ClassExists = False
For Each objSWbemObjectEx In objSWbemServicesEx.SubclassesOf()
If StrComp(objSWbemObjectEx.Path_.RelPath, strClassName, vbTextCompare) = 0 Then
ClassExists = True
Exit Function
End If
Next
End Function
Sub Sink_OnObjectReady(objWbemObject, objWbemAsyncContext)
Dim strComputer
strComputer = objWbemAsyncContext.Item("HostName")
If Not IsNull(objWbemObject.StatusCode) Then
If objWbemObject.StatusCode = 0 Then
objWmiNamedValueSet.Add "AgentAddress", strComputer
objWmiNamedValueSet.Add "AgentReadCommunityName", "poll"
'On Error Resume Next
If ClassExists(objWmiServices, "SNMP_RFC1213_MIB_system") Then
Set colSystem = objWmiServices.InstancesOf("SNMP_RFC1213_MIB_system", , objWmiNamedValueSet)
For Each objSystem In colSystem
If (Right(objSystem.sysName,12)=".123456789012") Then
objSystem.sysName=Left(objSystem.sysName,Len(objSystem.sysName)-12) + ".m"
Else
objSystem.sysName=objSystem.sysName + ".m"
End If
NFile1.WriteLine objSystem.sysName + " IN A " + strComputer
Next
Else
' Здесь добавляете код для «прошёл пинг, но нет указанного класса».
End If
Else
' Здесь добавляете код для «пинг не прошёл».
End If
Else
' Здесь добавляете код для «пинг не прошёл».
End If
End Sub
Iska, ОК, спасиб, завтра буду пробовать.
А еще, не подскажете, как мне из строки вида "10.31.101.102" сформировать строку вида "102.101" в этой же функции после строки
"NFile1.WriteLine objSystem.sysName + " IN A " + strComputer "
?
Ну то есть, брать 2 последних октета из strComputer и их поменять местами? А то как не пробую - у меня все type mismatch вылезает.
Да, я понял, что так писать нельзя (без обявления переменных), но с нуля сложно пока для меня за всеми переменными уследить, да еще и без отладчика, в блокноте. (((
Ну то есть, брать 2 последних октета из strComputer и их поменять местами? »
Проще всего — разбить строку на массив октетов и взять два последних из четырёх, поменяв их местами.
WScript.Echo Split("10.31.101.102", ".")(3) & "." & Split("10.31.101.102", ".")(2)
Option Explicit
Dim strValue
Dim arrValues
strValue = "10.31.101.102"
arrValues = Split(strValue, ".")
WScript.Echo arrValues(3) & "." & arrValues(2)
WScript.Quit 0
Да, я понял, что так писать нельзя (без обявления переменных),»
Писать можно, но отслеживание в этом случае возможных описок весьма тяжело даётся.
но с нуля сложно пока для меня за всеми переменными уследить, да еще и без отладчика, в блокноте. ((( »
Консоль наше всё :):
http://i.imgur.com/HzH104m.png
http://i.imgur.com/krZbSQ8.png
Я ж Вам писал:
glukin, редактор Far Manager'а, SciTE. VBSEdit также весьма хорош (но не бесплатен). »
Iska, Я так понимаю, что это будет работать, только если "101.102", а если "1.2"? То есть октеты не обязательно будут в 3 символа.
В Фаре не нашел такой функциональности, VBSEdit хорош, но пошаговой отладки тоже там не нашел.
Да и платить не хочется. )))
Iska, Я так понимаю, что это будет работать, только если "101.102", а если "1.2"? То есть октеты не обязательно будут в 3 символа. »
Будет работать. Функция Split() разбивает строку в массив на составляющие по разделителю, в данном случае — по точке.
В Фаре не нашел такой функциональности, »
Я пришёл к выводу, что лучшая отладка — консоль и WScript.Echo.
VBSEdit хорош, но пошаговой отладки тоже там не нашел. »
http://i.imgur.com/iWdLjgf.png
В принципе, можно пользовать Microsoft Script Debugger. При наличии Microsoft Office, использовать тамошний отладчик из редактора Microsoft Script Editor, но, повторюсь: для меня самый быстрый способ — редактор и консоль Far Manager'а.
Iska, добрый день, наконец-то у меня дошли руки до скрипта.
Вы писали: "Попробуйте так (добавить всё ту же функцию):"
Все равно не работает, выдает ошибку, когда натыкается на устройство без SNMP - тот же (null)
---------------------------
Windows Script Host
---------------------------
Script: C:\Documents and Settings\rp\Desktop\ping1.vbs
Line: 120
Char: 12
Error: 0x80041010
Code: 80041010
Source: (null)
---------------------------
OK
---------------------------
Вот код процедуры, что я делаю не так?
Sub Sink_OnObjectReady(objWbemObject, objWbemAsyncContext)
Dim strComputer
strComputer = objWbemAsyncContext.Item("HostName")
If Not IsNull(objWbemObject.StatusCode) Then
If objWbemObject.StatusCode = 0 Then
objWmiNamedValueSet.Add "AgentAddress", strComputer
objWmiNamedValueSet.Add "AgentReadCommunityName", "poll"
'on error resume next
If ClassExists(objWmiServices, "SNMP_RFC1213_MIB_system") Then
Set colSystem = objWmiServices.InstancesOf("SNMP_RFC1213_MIB_system", , objWmiNamedValueSet)
For Each objSystem In colSystem
If (Right(objSystem.sysName,12)=".123456789012") Then
objSystem.sysName=Left(objSystem.sysName,Len(objSystem.sysName)-12) + ".m"
Else
objSystem.sysName=objSystem.sysName + ".m"
End If
NFile1.WriteLine objSystem.sysName + " IN A " + strComputer
Next
Else
WScript.Echo "OK"
NoSNMP.WriteLine strComputer
End If
End If
End If
End Sub
Line 120, на которую ругается, выделена жирным.
Спасибо.
Добавил отладки, в жирную ветку функции, которую Вы посоветовали, не попадает. ((
Function ClassExists(objSWbemServicesEx, strClassName)
Dim objSWbemObjectEx
ClassExists = False
For Each objSWbemObjectEx In objSWbemServicesEx.SubclassesOf()
If StrComp(objSWbemObjectEx.Path_.RelPath, strClassName, vbTextCompare) = 0 Then
ClassExists = True
WScript.Echo "GOOD"
Exit Function
End If
Next
WScript.Echo "BAD"
End Function
glukin, такое ощущение, что класс есть, а экземпляров класса нет. Попробуйте всё-таки вместо прямого обращения к коллекции по .InstancesOf("SNMP_RFC1213_MIB_system"…) сделать запрос посредством .ExecQuery("SELECT * FROM SNMP_RFC1213_MIB_system"…).
Мне, к сожалению, банально даже не на чем проверить.
Iska, Ничего не понимаю.
Попробовал дома на устройствах, которые точно не умеют SNMP - все работает!
Дома Win7 Ultimate, где ошибка - Win2003, может, дело в версиях винды и 2003-я винда не умеет, то что Вы написали?
Только проблема в том, что дома наоборот - нет того, кто бы умел SNMP, полностью работу не проверишь. ))
Iska, Добавлю: убрал проверку на ClassExists, ошибка вылетает такая же, то есть в Win2003 не работает функция ClassExists, а в Win7 она работает.
Проверить можно на локалхосте (127.0.0.0-255).
Help!
Iska, "glukin, такое ощущение, что класс есть, а экземпляров класса нет. Попробуйте всё-таки вместо прямого обращения к коллекции по .InstancesOf("SNMP_RFC1213_MIB_system"…) сделать запрос посредством .ExecQuery("SELECT * FROM SNMP_RFC1213_MIB_system"…)."
Все то же самое...
---------------------------
Windows Script Host
---------------------------
Script: C:\Documents and Settings\rp\Desktop\ping1.vbs
Line: 121
Char: 12
Error: 0x80041010
Code: 80041010
Source: (null)
---------------------------
OK
---------------------------
На той же строке.
glukin, что мне потребуется для того, чтобы проверить у себя работу Вашего скрипта?
Iska, сделал через If Error Resume Next, так что думаю на этом и остановиться.
Спасибо.
Iska, впрочем, если есть желание и время, можете попробовать, вот код для локалхоста, но нужен или win2003 server или winXP. Ибо на 7-ке все работает.
File_Out1 = "C:\SNMP.txt"
File_Out2 = "C:\30.10.txt"
File_out3 = "C:\31.10.txt"
File_Date = "C:\date.txt"
File_NoSNMP = "C:\NoSNMP.txt"
Set objWmiLocator = CreateObject("WbemScripting.SWbemLocator")
Set objWmiServices = objWmiLocator.ConnectServer("", "root\snmp\localhost")
Set objWmiNamedValueSet = CreateObject("WbemScripting.SWbemNamedValueSet")
Set FSO = CreateObject("Scripting.FileSystemObject")
Set NFile1 = FSO.OpenTextFile(File_Out1, 2, True)
Set NFile2 = FSO.OpenTextFile(File_Out2, 2, True)
Set NFile3 = FSO.OpenTextFile(File_Out3, 2, True)
Set DateFile = FSO.OpenTextFile(File_Date, 2, True)
Set NoSNMP = FSO.OpenTextFile(File_NoSNMP, 2, True)
Dim arrComputers(256)
k = 0
For i = 0 To 0
For j = 0 To 255
arrComputers(k) = "127.0." + CStr(i) + "." + CStr(j)
k = k + 1
Next
Next
Dim strComputer
Dim objSWbemServicesEx
Dim objSWbemSink
Dim objSWbemNamedValueSet
Dim lngCount
Dim lngQueueCurrLength, lngQueueMaxLength
Dim i
' Максимальная длина очереди (в данном примере — сколько машин будут пинговаться одновременно),
' выбирается произвольно
lngQueueMaxLength = 10
' Текущая длина очереди
lngQueueCurrLength = 0
lngCount = UBound(arrComputers)
i = 0
Set objSWbemServicesEx = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\Root\CIMV2")
Set objSWbemSink = WScript.CreateObject("WbemScripting.SWbemSink", "Sink_")
While (i <= lngCount) Or (lngQueueCurrLength > 0) ' Пингуем пока не кончатся компы и очередь
If (i <= lngCount) And (lngQueueCurrLength < lngQueueMaxLength) Then
' В коллекции «objSWbemNamedValueSet» будем передавать адрес/имя хоста (замечание: в данном конкретном случае
' сие, в принципе, необязательно, поскольку класс Win32_PingStatus и так содержит
' свойство «.Address», но тут показана сама технология передачи данных в процедуру асинхронной обработки)
Set objSWbemNamedValueSet = WScript.CreateObject("WbemScripting.SWbemNamedValueSet")
objSWbemNamedValueSet.Add "HostName", arrComputers(i)
' Все запросы будут обрабатываться в единственной процедуре обработки
objSWbemServicesEx.ExecQueryAsync objSWbemSink, "SELECT * FROM Win32_PingStatus WHERE ADDRESS = '" & arrComputers(i) & "'", , , , objSWbemNamedValueSet
i = i + 1
lngQueueCurrLength = lngQueueCurrLength + 1
Else
' Ожидаем, пока не будут обработаны все асинхронные запросы
WScript.Sleep 100
End If
Wend
objSWbemSink.Cancel
Set objSWbemSink = Nothing
Set objSWbemServicesEx = Nothing
NFile1.Close
NFile2.Close
NFile3.Close
NoSNMP.Close
DateFile.Close
WScript.Quit 0
'=============================================================================
'=============================================================================
' Процедура асинхронной обработки экземпляра объекта (замечание: в данном конкретном случае
' будет возвращаться единственный объект, однако, в большинстве случаев запросы
' возвращают множество объектов)
Sub Sink_OnObjectReady(objWbemObject, objWbemAsyncContext)
Dim strComputer
strComputer = objWbemAsyncContext.Item("HostName")
If Not IsNull(objWbemObject.StatusCode) Then
If objWbemObject.StatusCode = 0 Then
objWmiNamedValueSet.Add "AgentAddress", strComputer
objWmiNamedValueSet.Add "AgentReadCommunityName", "public"
'on error resume next
If ClassExists(objWmiServices, "SNMP_RFC1213_MIB_system") Then
Set colSystem = objWmiServices.ExecQuery("SELECT sysName FROM SNMP_RFC1213_MIB_system",,, objWmiNamedValueSet)
For Each objSystem In colSystem
If (Right(objSystem.sysName,12)=".12345678901") Then
objSystem.sysName=Left(objSystem.sysName,Len(objSystem.sysName)-12) + ".m"
Else
objSystem.sysName=objSystem.sysName + ".m"
End If
NFile1.WriteLine objSystem.sysName + " IN A " + strComputer
Next
Else
' WScript.Echo "OK"
NoSNMP.WriteLine strComputer
End If
End If
End If
End Sub
'=============================================================================
'=============================================================================
' Процедура, вызываемая при завершении асинхронной обработки
Sub Sink_OnCompleted(iHResult, objWbemErrorObject, objWbemAsyncContext)
objWbemAsyncContext.DeleteAll
Set objWbemAsyncContext = Nothing
' Уменьшаем длину очереди
lngQueueCurrLength = lngQueueCurrLength - 1
'lngCount = lngCount - 1
End Sub
'==============================================================================
Function ClassExists(objSWbemServicesEx, strClassName)
Dim objSWbemObjectEx
ClassExists = False
For Each objSWbemObjectEx In objSWbemServicesEx.SubclassesOf()
If StrComp(objSWbemObjectEx.Path_.RelPath, strClassName, vbTextCompare) = 0 Then
ClassExists = True
' WScript.Echo "GOOD"
Exit Function
End If
Next
' WScript.Echo "BAD"
End Function
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.