Adding New EventLog Constants
We will add the constants shown in Listing 1 to the top of the modService.vb file so that we can write the correct EventID to the Application log.
Listing 1. Application log EventID constants.
Public Const WMI_ERROR As Integer = 1010
Public Const WMI_INFO As Integer = 2007
Public Const CONFIG_READ_ERROR As Integer = 4000
|
Updating <Tutorials.ThreadFunc>
Listing 2 shows the updated <ThreadFunc> method.
Listing 2. Updated <ThreadFunc> method.
Private Sub ThreadFunc()
While Not m_ThreadAction.StopThread
If Not m_ThreadAction.Pause Then
Try
Dim tmpWMI As New WMI
If Not tmpWMI.Connect(".") Then
WriteLogEvent("Thread WMI Connection Error - " +
tmpWMI.GetError, WMI_ERROR, EventLogEntryType.Error, "Tutorials")
Else
'Now process the file
Dim pMOC As ManagementObjectCollection
'Run our Query for SystemInfo
pMOC = tmpWMI.Query(Nothing, WMI.Management_Query_Type.SystemINfo)
If Not pMOC Is Nothing Then
Dim Name As String = Nothing
Dim Domain As String = Nothing
Dim Status As String = Nothing
Dim NumberOfProcessors As String = Nothing
Dim TotalPhysicalMemory As String = Nothing
Dim pMO As ManagementObject
For Each pMO In pMOC
Try
ReadProperty(pMO, "Name", Name)
ReadProperty(pMO, "Domain", Domain)
ReadProperty(pMO, "Status", Status)
ReadProperty(pMO, "NumberOfProcessors",
NumberOfProcessors)
ReadProperty(pMO, "TotalPhysicalMemory",
TotalPhysicalMemory)
Catch ex As Exception
Exit For
End Try
'Lets Log This Information
Dim pszOut As String
pszOut = "Name: " + Name.Trim
pszOut += ",Domain: " + Domain.Trim
pszOut += ",Status: " + Status.Trim
pszOut += ",NumberOfProcessors: " +
NumberOfProcessors.Trim
pszOut += ",TotalPhysicalMemory: " +
TotalPhysicalMemory.Trim + vbCrLf
WriteLogEvent(pszOut, WMI_INFO,
EventLogEntryType.Information, "Tutorials")
Next
Else
WriteLogEvent("Thread WMI query Error - " +
tmpWMI.GetError, WMI_ERROR, EventLogEntryType.Error,
"Tutorials")
End If
End If
WriteLogEvent("Thread Function Information - " +
Now.ToString, 1005, EventLogEntryType.Information,
"Tutorials")
Catch tab As ThreadAbortException
'this must be listed first as Exception is the master catch
'Clean up the thread here
WriteLogEvent("Thread Function Abort Error - " +
Now.ToString, 1006, EventLogEntryType.Error, "Tutorials")
Catch ex As Exception
WriteLogEvent("Thread Function Error - " + Now.ToString,
1005, EventLogEntryType.Error, "Tutorials")
End Try
End If
If Not m_ThreadAction.StopThread Then
Thread.Sleep(THREAD_WAIT)
End If
End While
End Sub
|
The example shown in Listing 2
allows us to read and then log information about the system that we
have queried. One thing you’ll notice about the WMI class is that we
used the built-in query for Win32_ComputerSystem;
however, because we knew exactly what information we were querying, we
could have written the query ourselves to limit the amount of data that
was returned. This is a very good idea when you are querying a large
number of servers over a network interface. Not only will the amount of
data traffic and memory requirements be reduced, but it will also speed
up your application.
Adding the WMI Property Reader Method
When we use the WMI class implementation to run
our predefined queries, we will be returned an object with a specific
set of properties exposed. To manage the reading of these properties,
I’ve implemented the code in Listing 3
to facilitate reading the property and returning the value to the
calling method. This method will be added to our existing Tutorials.vb
class implementation.
Listing 3. WMI property reading method implementation for Tutorials.vb.
Private Sub ReadProperty(ByRef pObject As ManagementObject,
ByRef pProp As String, ByRef pszStr As String)
Try
pszStr = pObject.Properties(pProp).Value.ToString
Catch ex As Exception
pszStr = ""
End Try
End Sub
|
This method attempts to read the value of the
property defined in the parameter list called pProp, and setting the
outgoing pointer, pszStr, to the string value of the property. If the
property is not valid or an exception occurs, the return parameter is
assigned a null value.
The previous code was
fairly simple. We used a WMI class to connect to the server, and then we
queried the WMI class that we wanted information about, assigning the
result of that query to our local ManagementObjectCollection. When you
call a WMI class using System.Management, nearly every object returns
two types of collections: the objectname collection
and the Enumerator collection. You can use either collection to access
the objects that were returned. When you perform the query, you are
returned a ManagementObject-Collection, which contains all the objects
from your query, such as each Logicaldisk or Adapter. Each object within
the collection has a Properties collection. The difference between the
collection interface and the Enumerator collection interface is that the
Enumerator class allows you to access
objects within the collection as if it were a database result set, in
that it holds a pointer to the previous and next objects available. When
you use the standard collection, you would normally loop through with a
For Each loop, but you have no direct bookmark into the collection, so
accessing it initially and then accessing it later will not hold your
place. Using the Enumerator rectifies this.