vb.net

位置:IT落伍者 >> vb.net >> 浏览文章

VB.NET开发扫描客户端服务工具


发布日期:2023年05月21日
 
VB.NET开发扫描客户端服务工具

在大中型企业信息系统中对客户端PC的管理往往是容易出现问题的环节因此很多大公司引入了各种分布式的管理系统例如防病毒方面的Norton AntiVirusBlackICE防火墙微软的 SMS (System Management Server)等等这些系统都会在客户端安装相应的客户端软件一般都是以服务的形式出现但是由于种种原因这些服务会停止运行或者该客户机根本没有安装这些客户端服务这样管理系统就会出现疏漏有可能造成问题如因无法防御病毒而成为病毒源无法为该客户端发布软件无法管理客户PC等等在此我们提供一个方案可以定时按照IP地址扫描网络报告出特定的服务的状态

这个方案使用了MicrosoftNET技术同时也用到了NET Framework中的ADONET WMI managementXML其核心是一个由VBNET写的程序以及它的两个配置文件配置文件为XML格式该程序按IP扫描网络得到每个系统的服务 的状态如果IP地址没有对应系统则忽略该IP针对没有安装服务或服务停止的系统我们在另一个线程中运行NBTSTAT命令得到其机器名用户名MAC地址域等信息以便我们找到机器解决问题其次为了保存扫描的结果我们需要一个很小的数据库MSAccess或MSSQL server都可以本文使用SQL 最后为了呈现出扫描的结果以便我们采取行动这里我们使用网页的形式把数据库中的结果展现出来

VBNET程序

该程序使用两个XML格式的配置文件当程序启动时会读入这些配置其中一个文件定义了需要扫描的网段包括排除在外的地址段另一个文件定义了连接数据库的信息以及数据表的定义这两个文件的内容如下

<IPLIST>

<IP LANID= ><EXP L= H=/></IP>

<IP LANID= />

<IP LANID= />

<IP LANID= />

<IP LANID= ><EXP L= H=/></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的属性定义了数据库中表名该表用于保存扫描结果

首先我们定义一个类主要用于得到某个IP地址的Service的状态信息并在服务状态不正常时触发另一线程得到该系统的详细信息

Imports SystemServiceProcess

Imports SystemXml

Imports SystemThreading

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类

ServicePMachineName = IMachineIP

ServicePServiceName = IServiceName

Dim myRow As DataRow

Dim status As String

Dim Run As Boolean = False

myRow = dsTables(ITable)NewRow

Try

If ServicePStatusToString <> Running Then

status = ServicePStatusToString如果状态不是RUNNING则将状态赋予字符串变量

Else

Run = True 如果状态为RUNNING则不做任何事

End If

Catch er As Exception 以下处理取得状态时候发生的异常

status = Left(erMessage )

If InStr(status Service Control Manager) = Then

status = Not installed or open service failed 没有安装该服务

ElseIf InStr(erMessage Manager) > Then

status = Can not detected 服务的状态不可得

End If

End Try

ServicePClose() 关闭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 HostInfo As New HostInfo(IMachineIP)

Dim HostThr As New Thread(New ThreadStart(AddressOf HostInfosysInfo))

HostThrStart()

SyncLock GetType(HostInfoThreadCounter)

HostInfoThreadCountercounter += 启动线程数加

End SyncLock

End If

SyncLock GetType(StoppCounter)

StopThrAddStop()

End SyncLock

End Sub

End Class

该类只有一个方法就是将停止的线程数减

Class StoppCounter

Sub AddStop()

ThreadCounterStopped = ThreadCounterStopped +

End Sub

End Class

此类用于将已有的行插入DataSet

Class AddRow

第一个构造函数以构造好的行为输入参数

Sub New(ByVal row As DataRow)

Try

dsTables()RowsAdd(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 dsTables()Select(IP= & IP & )

RowTimeOutItem(LastUID) = user

RowTimeOutItem(Name) = hostname

RowTimeOutItem(Mac) = Mac

RowTimeOutItem(Domain) = domain

RowTimeOutItem(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 SystemThreading 用于支持多线程

Imports SystemXml 用于分析XML格式的参数文件

Imports SystemData 用于保存结果到数据库

Module Module

Public ds As New DataSet()

Public conn As SqlClientSqlConnection 数据库连接

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 XmlXmlDocument()

Dim iplist As XmlXmlNode

Dim ipitem As XmlXmlNode

Dim DBinfoF As New XmlXmlDocument()

Dim DBinfo As XmlXmlNode

Dim LanID As String

Dim i As Integer

Dim timestart As Integer

Dim ThreadCounterStarted As Integer

ThreadCounterStarted =

ThreadCounterStopped =

Dim server As String

Dim database As String

Dim uid As String

Dim pwd As String

Dim table As String

Dim connstr connstr As String

Dim ServiceName As String

Dim Purgestr As String

Try

DBinfoFLoad(dbf) 读取数据库信息文件

Catch nodb As Exception

MsgBox(nodbMessage & Wrong DB info file name)

Exit Sub

End Try

Try

iplistFLoad(ipf) 读取IP列表文件

Catch noip As Exception

MsgBox(noipMessage & Wrong IP list file name)

Exit Sub

End Try

分析数据库信息文件

DBinfo = DBinfoFChildNodes()

server = DBinfoChildNodes()InnerText

database = DBinfoChildNodes()InnerText

uid = DBinfoChildNodes()InnerText

pwd = DBinfoChildNodes()InnerText

ServiceName = DBinfoChildNodes()InnerText

table = DBinfoChildNodes()Attributes()Value

根据分析所得构造连接字符串

connstr = server= & server & ;database= & database & ;uid= & uid & ;password= & pwd

conn = New SqlClientSqlConnection(connstr) 实例化数据库连接

connOpen() 打开数据库连接

Dim sa As SqlClientSqlDataAdapter = New SqlClientSqlDataAdapter(select * from & table conn)

Dim combu As New SqlClientSqlCommandBuilder(sa)

saFill(ds table) 填充DataSet

dsClear() 清空旧的数据

Dim IPAddress As String

分析IP列表文件

iplist = iplistFChildNodes()

Dim Ai As Integer

Dim ipexcepCount As Integer

Dim ipexcep As XmlXmlNode

For Each ipitem In iplistChildNodes

Dim Excep( ) As Integer

LanID = ipitemAttributes()Value得到网络ID

For i = To 根据每个网络ID构造IP地址

Ai =

以下判断是为了跳过保留地址段

If ipitemHasChildNodes Then

ipexcepCount = ipitemChildNodesCount

ReDim Excep( ipexcepCount )

For Each ipexcep In ipitemChildNodes

Excep( Ai) = CInt(ipexcepAttributes()Value)

Excep( Ai) = CInt(ipexcepAttributes()Value)

Ai = Ai +

Next

End If

For Ai = To ipexcepCount

If i >= Excep( Ai) And i <= Excep( Ai) Then

ConsoleWriteLine(跳过保留地址 & LanID & iToString)

GoTo SkipIP

End If

Next

machineIP = LanID & iToString IP地址

以下触发线程以得到服务状态

Dim getSt As New GetStatus(machineIP ServiceName table)

Dim GetStThread As New Thread(New ThreadStart(AddressOf getStGetStausF))

GetStThreadStart()

ThreadCounterStarted = ThreadCounterStarted + 启动线程数加

ConsoleWriteLine(线程 & machineIP & 启动检测 & ServiceName)

每启动个线程程序主线程停止避免太多线程造成内存溢出

If (ThreadCounterStarted Mod ) = Then

ConsoleWriteLine(等待 )

ThreadCurrentThreadSleep()

GCCollect() force garbage collection to aviod outOfMemory when run with long IP list

End If

SkipIP:

Next

Next

ConsoleWriteLine(Exiting program ) 所有线程都已触发

Finish:

ThreadCurrentThreadSleep() 以下程序等待所有线程结束

GCCollect()

If ThreadCounterStopped = ThreadCounterStarted And HostInfoThreadCountercounter = HostInfoThreadCountercounterSTOP Then如果触发线程等于结束线程

Dim row As DataDataRow

For Each row In dsTables(table)Rows

rowItem(SysTime) = Now

Next

Purgestr = delete & table

Dim com As New SqlClientSqlCommand(Purgestr conn)

comExecuteNonQuery() 删除旧记录

saInsertCommand = combuGetInsertCommand

saUpdate(ds table) 将新记录写入数据库

Else

GoTo Finish goto finish and wait another seconds

End If

End Sub

可以利用如下命令在DOS窗口启动该程序

Scanservice –i iplistxml –d dbinfoxml

SCANSERVICE 数据库

该数据库保存保存程序运行结果以便用WEB等方式展现出来以下是建立表的脚本包含域名用户名机器名IP以及服务状态

CREATE TABLE [dbo][Service] (

[IP] [varchar] () NULL

[状态] [varchar] () NULL

[用户名] [varchar] () NULL

[机器名] [varchar] () NULL

[MAC地址] [varchar] () NULL

[域] [varchar] () NULL

[超时] [varchar] () NULL

[时间安] [DateTime] () NULL

)

总结

以上是一个完整的方法也是比较简单明晰的解决方法如果要求技巧和性能的话还有一些地方可以做些改进比如对线程池的使用另外还有一些方面需要大家自己完成比如将数据库中的信息以WEB的方式展现出来

               

上一篇:如何轻松调整VB.NET控件

下一篇:完整的VB.NET的语法解析程序