VB.NET開發掃描用戶端服務工具

來源:互聯網
上載者:User
用戶端   在大中型公司資訊系統中,對用戶端PC的管理,往往是容易出現問題的環節。因此,很多大公司引入了各種分布式的管理系統,例如防病毒方面的Norton AntiVirus,BlackICE防火牆,微軟的 SMS (System Management Server),等等,這些系統都會在用戶端安裝相應的用戶端軟體,一般都是以服務的形式出現,但是由於種種原因,這些服務會停止運行或者該客戶機根本沒有安裝這些用戶端服務,這樣管理系統就會出現疏漏,有可能造成問題,如因無法防禦病毒而成為病毒源,無法為該用戶端發布軟體,無法管理客戶PC等等。在此,我們提供一個方案,可以定時按照IP地址掃描網路,報告出特定的服務的狀態。

  這個方案使用了Microsoft.NET技術,同時也用到了.NET Framework中的ADO.NET ,WMI management,XML。其核心是一個由VB.NET寫的程式以及它的兩個設定檔,設定檔為XML格式,該程式按IP掃描網路,得到每個系統的服務 的狀態,如果IP地址沒有對應系統,則忽略該IP,針對沒有安裝服務或服務停止的系統我們在另一個線程中運行NBTSTAT命令,得到其機器名,使用者名稱,MAC地址域等資訊,以便我們找到機器解決問題。其次為了儲存掃描的結果,我們需要一個很小的資料庫MS-Access或MS-SQL server都可以,本文使用SQL2000 。最後為了呈現出掃描的結果,以便我們採取行動,這裡我們使用網頁的形式把資料庫中的結果展現出來。

  1. VB.NET程式

  該程式使用兩個XML格式的設定檔,當程式啟動時會讀入這些配置。其中一個檔案定義了需要掃描的網段,包括排除在外的位址區段。另一個檔案定義了串連資料庫的資訊,以及資料表的定義。這兩個檔案的內容如下:

<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>


  該檔案定義將要掃描5個網段,其中兩個網段有些地址需要排除在外(分配給印表機等裝置),對於192.168.100段,我們排除從1到30,對於192.168.104段我們排除1到40。

<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 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


  2. SCANSERVICE 資料庫

  該資料庫儲存儲存程式運行結果,以便用WEB等方式展現出來。以下是建立表的指令碼,包含網域名稱,使用者名稱,機器名,IP以及服務狀態。

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 ,

)

  總結:

  以上是一個完整的方法,也是比較簡單明晰的解決方案,如果要求技巧和效能的話,還有一些地方可以做些改進,比如對線程池的使用。另外還有一些方面需要大家自己完成,比如將資料庫中的資訊以WEB的方式展現出來。

相關文章

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。