<IPLIST> <IP LANID="192.168.100." ><EXP L=”1” H=”30”/></IP> <IP LANID="192.168.101." /> <IP LANID="192.168.102." /> <IP LANID="192.168.103." /> <IP LANID="192.168.104." ><EXP L=”1” H=”40”/></IP> </IPLIST> |
<DBINFO> <SERVER>DBServer</SERVER> <DATABASE>DB</DATABASE> <UID>REPORT</UID> <PWD>REPORT</PWD> <SERVICE TABLE=”SERVICE”>SERVICE</SERVICE> </DBINFO> |
TAG | Meaning |
<SERVER> | SCANSERVICE数据库的服务器名 |
<DATABASE> | SCANSERVICE数据库名 |
<UID> | 用于更新SCANSERVICE数据库的数据库用户名 |
<PWD> | 用于更新SCANSERVICE数据库的数据库用户的密码 |
<SERVICE> | 该TAG的 inner 定义了我们希望扫描的Service的名字, 这里我们假定希望扫描服务名为SERVICE。 该TAG的属性定义了数据库中表名,该表用于保存扫描结果。 |
Imports System.ServiceProcess Imports System.XML Imports System.Threading Public Class GetStatus Private IServiceName As String ‘服务的名称 Private IMachineIP As String ‘IP地址 Private ITable As String ‘在DATESET中的表名 ‘构造函数 Sub New(ByVal Ip As String, ByVal SVCName As String, ByVal updatetable As String) IMachineIP = Ip IServiceName = SvcName ITable = updatetable End Sub ‘每个线程所运行的方法,用于得到服务的状态,如果状态不正常则触发另一线程得到该IP的信息 Sub GetStausF() Dim ServiceP As New ServiceController() ‘实例化一个ServiceController类 ServiceP.MachineName = IMachineIP ServiceP.ServiceName = IServiceName Dim myRow As DataRow Dim status As String Dim Run As Boolean = False myRow = ds.Tables(ITable).NewRow Try If ServiceP.Status.ToString <> "Running" Then status = ServiceP.Status.ToString‘如果状态不是RUNNING则将状态赋予字符串变量 Else Run = True ‘如果状态为RUNNING,则不做任何事 End If Catch er As Exception ‘以下处理取得状态时候发生的异常 status = Left(er.Message, 35) If InStr(status, "Service Control Manager") = 0 Then status = "Not installed or open service failed" ‘没有安装该服务 ElseIf InStr(er.Message, "Manager") > 0 Then status = "Can not detected" ‘服务的状态不可得 End If End Try ServiceP.Close() ‘关闭ServiceController实例 ‘以下判断如果状态不是RUNNING,则记录该系统,并触发线程得到它的详细信息。 If Not Run Then myRow("msg") = status myRow("ip") = IMachineIP SyncLock GetType(AddRow) ‘为保证多线程情况下,对DataSet只有一个写操作,锁定AddRow类 Dim AddRowIns As New AddRow(myRow) ‘将IP和状态通过我们自己写的AddRow类插入DataSet End SyncLock ‘触发另一线程取得机器信息 Dim HostInfo2 As New HostInfo(IMachineIP) Dim HostThr2 As New Thread(New ThreadStart(AddressOf HostInfo2.sysInfo)) HostThr2.Start() SyncLock GetType(HostInfoThreadCounter) HostInfoThreadCounter.counter += 1 ‘启动线程数加1 End SyncLock End If SyncLock GetType(StoppCounter) StopThr.AddStop() End SyncLock End Sub End Class ‘该类只有一个方法,就是将停止的线程数减1 Class StoppCounter Sub AddStop() ThreadCounterStopped = ThreadCounterStopped + 1 End Sub End Class ‘此类用于将已有的行插入DataSet Class AddRow ‘第一个构造函数,以构造好的行为输入参数 Sub New(ByVal row As DataRow) Try ds.Tables(0).Rows.Add(row) Catch ee As Exception End Try End Sub ‘第二个构造函数,以机器名用户名等字符串为参数,更新已有的行 Sub New(ByVal IP As String, ByVal user As String, ByVal hostname As String, ByVal Mac As String, ByVal domain As String, ByVal timeout As Char) Dim RowTimeOut As DataRow Try For Each RowTimeOut In ds.Tables(0).Select("IP='" & IP & "'") RowTimeOut.Item("LastUID") = user RowTimeOut.Item("Name") = hostname RowTimeOut.Item("Mac") = Mac RowTimeOut.Item("Domain") = domain RowTimeOut.Item("Timeout") = timeout 'Set timeout flag to this item Exit For 'just run once Next Catch er As Exception End Try End Sub End Class ‘由于篇幅限制,这里省略了根据IP取得机器信息的类的代码。 Imports System.Threading ‘用于支持多线程 Imports System.XML ‘用于分析XML格式的参数文件 Imports System.Data ‘用于保存结果到数据库 Module Module1 Public ds As New DataSet() Public conn1 As SqlClient.SqlConnection ‘数据库连接 Public ipf As String ‘IP列表文件名 Public dbf As String ‘数据库信息文件 Public ThreadCounterStopped As Integer Public StopThr As New StoppCounter() Sub Main() ‘程序主程序 Dim machineIP As String Dim iplistF As New Xml.XmlDocument() Dim iplist As Xml.XmlNode Dim ipitem As Xml.XmlNode Dim DBinfoF As New Xml.XmlDocument() Dim DBinfo As Xml.XmlNode Dim LanID As String Dim i As Integer Dim timestart As Integer Dim ThreadCounterStarted As Integer ThreadCounterStarted = 0 ThreadCounterStopped = 0 Dim server As String Dim database As String Dim uid As String Dim pwd As String Dim table As String Dim connstr, connstr1 As String Dim ServiceName As String Dim Purgestr As String Try DBinfoF.Load(dbf) ‘读取数据库信息文件 Catch nodb As Exception MsgBox(nodb.Message & "Wrong DB info file name.") Exit Sub End Try Try iplistF.Load(ipf) ‘读取IP列表文件 Catch noip As Exception MsgBox(noip.Message & "Wrong IP list file name.") Exit Sub End Try ‘分析数据库信息文件 DBinfo = DBinfoF.ChildNodes(0) server = DBinfo.ChildNodes(0).InnerText database = DBinfo.ChildNodes(1).InnerText uid = DBinfo.ChildNodes(2).InnerText pwd = DBinfo.ChildNodes(3).InnerText ServiceName = DBinfo.ChildNodes(4).InnerText table = DBinfo.ChildNodes(4).Attributes(0).Value ‘根据分析所得,构造连接字符串 connstr1 = "server=" & server & ";database=" & database & ";uid=" & uid & ";password=" & pwd conn1 = New SqlClient.SqlConnection(connstr1) ‘实例化数据库连接 conn1.Open() ‘打开数据库连接 Dim sa As SqlClient.SqlDataAdapter = New SqlClient.SqlDataAdapter("select * from " & table, conn1) Dim combu As New SqlClient.SqlCommandBuilder(sa) sa.Fill(ds, table) ‘填充DataSet ds.Clear() ‘清空旧的数据 Dim IPAddress As String ‘分析IP列表文件 iplist = iplistF.ChildNodes(0) Dim Ai As Integer Dim ipexcepCount As Integer Dim ipexcep As Xml.XmlNode For Each ipitem In iplist.ChildNodes Dim Excep(2, 83) As Integer LanID = ipitem.Attributes(0).Value‘得到网络ID For i = 2 To 254 ‘从2到254,根据每个网络ID构造IP地址 Ai = 0 ‘以下判断是为了跳过保留地址段 If ipitem.HasChildNodes Then ipexcepCount = ipitem.ChildNodes.Count ReDim Excep(2, ipexcepCount - 1) For Each ipexcep In ipitem.ChildNodes Excep(0, Ai) = CInt(ipexcep.Attributes(0).Value) Excep(1, Ai) = CInt(ipexcep.Attributes(1).Value) Ai = Ai + 1 Next End If For Ai = 0 To ipexcepCount - 1 If i >= Excep(0, Ai) And i <= Excep(1, Ai) Then Console.WriteLine("跳过保留地址: " & LanID & i.ToString) GoTo SkipIP End If Next machineIP = LanID & i.ToString ‘IP地址 ‘以下触发线程以,得到服务状态 Dim getSt As New GetStatus(machineIP, ServiceName, table) Dim GetStThread As New Thread(New ThreadStart(AddressOf getSt.GetStausF)) GetStThread.Start() ThreadCounterStarted = ThreadCounterStarted + 1‘启动线程数加1 Console.WriteLine("线程" & machineIP & " 启动。检测 " & ServiceName) ‘每启动100个线程,程序主线程停止15秒,避免太多线程造成内存溢出 If (ThreadCounterStarted Mod 100) = 0 Then Console.WriteLine("等待 .......") Thread.CurrentThread.Sleep(15000) GC.Collect() 'force garbage collection to aviod outOfMemory when run with long IP list End If SkipIP: Next Next Console.WriteLine("Exiting program ...") ‘所有线程都已触发 Finish: Thread.CurrentThread.Sleep(5000) ‘以下程序等待所有线程结束 GC.Collect() If ThreadCounterStopped = ThreadCounterStarted And HostInfoThreadCounter.counter = HostInfoThreadCounter.counterSTOP Then‘如果触发线程等于结束线程 Dim row As Data.DataRow For Each row In ds.Tables(table).Rows row.Item("SysTime") = Now Next Purgestr = "delete " & table Dim com1 As New SqlClient.SqlCommand(Purgestr, conn1) com1.ExecuteNonQuery() ‘删除旧记录 sa.InsertCommand = combu.GetInsertCommand sa.Update(ds, table) ' 将新记录写入数据库 Else GoTo Finish ' goto finish and wait another 30 seconds End If End Sub 可以利用如下命令在DOS窗口启动该程序。 Scanservice –i iplist.xml –d dbinfo.xml |
CREATE TABLE [dbo].[Service] ( [IP] [varchar] (50) NULL , [状态] [varchar] (50) NULL , [用户名] [varchar] (50) NULL , [机器名] [varchar] (50) NULL , [MAC地址] [varchar] (50) NULL , [域] [varchar] (50) NULL , [超时] [varchar] (10) NULL , [时间安] [DateTime] (8) NULL , ) |