Войти

Показать полную графическую версию : [решено] Помогите наваять скрипт? Поиск строки в файле.


Страниц : 1 [2]

glukin
07-03-2017, 20:37
Iska, Боюсь, что для меня это крутовато, не осилил. Пожалуй сделаю как-то так:
on error resume next
затем если (пинг прошел)&(была запись в файл) то NoSNMP=False
иначе NoSnmp=True
если NoSNMP то пишем в файл ИП-адрес "плохого" устройства

Только пока не разобрался с переходами по on error resume next

Трудно без нормального отладчика с контрольными точками и пошаговым выполнением команд (((


Покритикуйте алгоритм.

glukin
09-03-2017, 12:29
Прошу помощи в реализации на vbs.

Iska
09-03-2017, 12:47
Покажите Ваш текущий код (не забывайте обрамлять его тэгом «code»).

glukin
09-03-2017, 13:10
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"
то оно умеет, иначе пишем его ИП-адрес в файл для дальнейшего анализа.

Iska
09-03-2017, 13:25
glukin, это только одна процедура. Я имел в виду — весь код.

glukin
09-03-2017, 13:30
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

Iska
09-03-2017, 14:21
Тяжёлый код. Используйте 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

glukin
09-03-2017, 18:32
Iska, ОК, спасиб, завтра буду пробовать.
А еще, не подскажете, как мне из строки вида "10.31.101.102" сформировать строку вида "102.101" в этой же функции после строки
"NFile1.WriteLine objSystem.sysName + " IN A " + strComputer "
?
Ну то есть, брать 2 последних октета из strComputer и их поменять местами? А то как не пробую - у меня все type mismatch вылезает.
Да, я понял, что так писать нельзя (без обявления переменных), но с нуля сложно пока для меня за всеми переменными уследить, да еще и без отладчика, в блокноте. (((

Iska
09-03-2017, 18:58
Ну то есть, брать 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 также весьма хорош (но не бесплатен). »

glukin
09-03-2017, 19:18
Iska, Я так понимаю, что это будет работать, только если "101.102", а если "1.2"? То есть октеты не обязательно будут в 3 символа.
В Фаре не нашел такой функциональности, VBSEdit хорош, но пошаговой отладки тоже там не нашел.
Да и платить не хочется. )))

Iska
09-03-2017, 20:03
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'а.

glukin
14-03-2017, 16:57
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

Iska
14-03-2017, 18:53
glukin, такое ощущение, что класс есть, а экземпляров класса нет. Попробуйте всё-таки вместо прямого обращения к коллекции по .InstancesOf("SNMP_RFC1213_MIB_system"…) сделать запрос посредством .ExecQuery("SELECT * FROM SNMP_RFC1213_MIB_system"…).

Мне, к сожалению, банально даже не на чем проверить.

glukin
14-03-2017, 21:25
Iska, Ничего не понимаю.
Попробовал дома на устройствах, которые точно не умеют SNMP - все работает!
Дома Win7 Ultimate, где ошибка - Win2003, может, дело в версиях винды и 2003-я винда не умеет, то что Вы написали?
Только проблема в том, что дома наоборот - нет того, кто бы умел SNMP, полностью работу не проверишь. ))

glukin
15-03-2017, 09:38
Iska, Добавлю: убрал проверку на ClassExists, ошибка вылетает такая же, то есть в Win2003 не работает функция ClassExists, а в Win7 она работает.
Проверить можно на локалхосте (127.0.0.0-255).
Help!

glukin
15-03-2017, 21:21
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
---------------------------
На той же строке.

Iska
16-03-2017, 08:42
glukin, что мне потребуется для того, чтобы проверить у себя работу Вашего скрипта?

glukin
16-03-2017, 09:26
Iska, сделал через If Error Resume Next, так что думаю на этом и остановиться.
Спасибо.

glukin
16-03-2017, 11:24
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