Académique Documents
Professionnel Documents
Culture Documents
This article explains how you can retrieve Windows server information using both Visual
Basic.NET and VBScript, along with WMI.
The sample downloadable solution (zip) is entirely developed using Visual Studio.NET 2003
Enterprise Architect on Windows Server 2003 Standard Edition. But, I am confident that it
would work with other versions of Windows (which support .NET 1.1) versions as well.
Some global routines used for my WMI development
Let me first address some issues. I received a lot of feedback from several readers throughout
the world on my series “WMI Programming with Visual Basic.NET”. Almost every one (about
80%) requested that I extend the series with much more useful and helpful information about
working with WMI (in the form of tasks). Some of the readers also asked me to give examples
on VBScript as well (and not only VB.NET).
One should consider that WMI is being updated and enhanced almost every day. Microsoft is
also integrating WMI directly into some of its products. With humble thanks to every reader who
encouraged me to write more, I further extend the same series (but with a different naming
scheme). I will be including much more useful information, both for developers and system
administrators.
I keep on extending the same series as much as possible, covering almost all the aspects of
WMI. I strongly suggest you go through my series on “WMI Programming with Visual
Basic.NET” before reading this article. The series even covers “event handling” using WMI
with Visual Basic .NET in the form of Windows Service.
For flexibility in retrieving WMI information (using VB.NET), I frequently used the following
simple global routines which would help me to work with other areas of development very
easily.
Public Sub addRow(ByRef dt As DataTable, ByVal p As String, ByVal v As
String)
Dim dr As DataRow
dr = dt.NewRow
dr("Property") = p
dr("Value") = v
dt.Rows.Add(dr)
End Sub
Public Function getStructure() As DataTable
Dim dt As New DataTable
dt.Columns.Add(New DataColumn("Property"))
dt.Columns.Add(New DataColumn("Value"))
Return dt
End Function
Two of my global routines are “getStructure” and “addRow”. Both are generally used if I have
the “Property->value” scenario. “GetStructure” just creates a data table structure and “AddRow”
just adds a data row for every data table passed to it. And similarly, I also have the following
two, to work with “UserAccountInformation”.
Public Function getUserAccountStructure() As DataTable
Dim dt As New DataTable
dt.Columns.Add(New DataColumn("FullName"))
dt.Columns.Add(New DataColumn("Name"))
dt.Columns.Add(New DataColumn("Domain"))
dt.Columns.Add(New DataColumn("LocalAccount"))
Return dt
End Function
Public Sub addUserAccountRow(ByRef dt As DataTable, ByVal FullName As
String, ByVal Name As String, ByVal Domain As String, ByVal LocalAccount As
String)
Dim dr As DataRow
dr = dt.NewRow
dr("FullName") = FullName
dr("Name") = Name
dr("Domain") = Domain
dr("LocalAccount") = LocalAccount
dt.Rows.Add(dr)
End Sub
How can you find out information about your server? By this I mean its name, domain,
workgroup, and so on. The following VB.NET code should supply some minimum information
on your server.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Try
Dim searcher As New ManagementObjectSearcher( _
"root\CIMV2", _
"SELECT * FROM Win32_ComputerSystem")
Dim en As ManagementObjectEnumerator =
searcher.Get.GetEnumerator
If en.MoveNext Then
Dim queryObj As ManagementObject = en.Current
Dim dt As DataTable = globals.getStructure()
globals.addRow(dt, "Caption", queryObj
("Caption"))
globals.addRow(dt, "Name", queryObj("Name"))
globals.addRow(dt, "UserName", queryObj
("UserName"))
globals.addRow(dt, "DNSHostName", queryObj
("DNSHostName"))
globals.addRow(dt, "Description", queryObj
("Description"))
globals.addRow(dt, "PartOfDomain", queryObj
("PartOfDomain"))
globals.addRow(dt, "Domain", queryObj("Domain"))
globals.addRow(dt, "Workgroup", queryObj
("Workgroup"))
dt.AcceptChanges()
Me.DataGrid1.DataSource = dt
End If
How can we list all the user accounts on your server? The following VB.NET code would
achieve this result.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Try
Dim searcher As New ManagementObjectSearcher( _
"root\CIMV2", _
"SELECT * FROM Win32_UserAccount")
Dim dt As DataTable = globals.getUserAccountStructure
()
Dim en As ManagementObjectEnumerator =
searcher.Get.GetEnumerator
While en.MoveNext
Dim queryObj As ManagementObject = en.Current
globals.addUserAccountRow(dt, queryObj
("FullName"), queryObj("Name"), queryObj("Domain"), queryObj
("LocalAccount"))
End While
dt.AcceptChanges()
Me.DataGrid1.DataSource = dt
Catch err As ManagementException
MessageBox.Show("An error occurred while querying for WMI data:
" & err.Message)
End Try
End Sub
I excluded some of the properties (because it would make the program too long) from the
existing WMI class (Win32_UserAccount) to give you only the most important ones. The above
program would list the full name, user name, domain the user belongs to and whether or not it is
a local account. You can further extend the above program with several other properties
available in the “Win32_UserAccount” class. You can even refer to MSDN online for further
properties.
You can achieve the same result with VBScript by using the following code:
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
Set colItems = objWMIService.ExecQuery( _
"SELECT * FROM Win32_UserAccount",,48)
For Each objItem in colItems
Wscript.Echo "FullName: " & objItem.FullName
Wscript.Echo "Name: " & objItem.Name
Wscript.Echo "Domain: " & objItem.Domain
Wscript.Echo "LocalAccount: " & objItem.LocalAccount
Next
The following VB.NET code would give you the information on all user groups available
(whether or not the user group is part of a domain). It also includes user account information.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Try
Dim searcher As New ManagementObjectSearcher( _
"root\CIMV2", _
"SELECT * FROM Win32_AccountSID")
Dim dt As DataTable = globals.getStructure()
Dim en As ManagementObjectEnumerator =
searcher.Get.GetEnumerator
While en.MoveNext
Dim queryObj As ManagementObject = en.Current
globals.addRow(dt, "User: ", queryObj("Element"))
End While
dt.AcceptChanges()
Me.DataGrid1.DataSource = dt
Catch err As ManagementException
MessageBox.Show("An error occurred while querying for
WMI data: " & err.Message)
End Try
End Sub
You can achieve the same result by using VBScript code as follows:
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
Set colItems = objWMIService.ExecQuery( _
"SELECT * FROM Win32_AccountSID",,48)
For Each objItem in colItems
Wscript.Echo "Element: " & objItem.Element
Next
One should note that I used different WMI classes and properties for different scenarios. You
can get the full list of classes along with their properties and other documentation online at
MSDN online. Hundreds of classes exist in WMI to fetch even the most in-depth information
about your server.
You can change your computer name using VB.NET and WMI as shown in the following:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles Button1.Click
Try
Dim classInstance As New ManagementObject( _
"root\CIMV2", _
"Win32_ComputerSystem.Name='SERVER'", _
Nothing)
Dim inParams As ManagementBaseObject = _
classInstance.GetMethodParameters("Rename")
inParams("Name") = "server2" 'rename to
inParams("Password") = "admin"
inParams("UserName") = "administrator"
Dim outParams As ManagementBaseObject = _
classInstance.InvokeMethod("Rename", inParams,
Nothing)
MessageBox.Show("ReturnValue: {0}", outParams
("ReturnValue"))
Catch err As ManagementException
MessageBox.Show("Error: " & err.Message)
End Try
End Sub
Note that I am using “InvokeMethod” to execute a WMI method (in this case “Rename”)
dynamically. “inParams” (an object of ManagementBaseObject) is specifically used to pass
parameters to the WMI method “Rename”. It mainly contains the required information to
penetrate through the authentication and authorization (username and password) of security,
along with the new computer name. We can get the result after executing the WMI method
“Rename” into “outParams”.
You can achieve the same result using the following VBScript code:
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
Set objShare = objWMIService.Get("Win32_ComputerSystem.Name='SERVER'")
Set objInParam = objShare.Methods_("Rename").inParameters.SpawnInstance_()
objInParam.Properties_.Item("Name") = "server2"
objInParam.Properties_.Item("Password") = "admin"
objInParam.Properties_.Item("UserName") = "administrator"
Set objOutParams =
objWMIService.ExecMethod("Win32_ComputerSystem.Name='SERVER'", "Rename",
objInParam)
Wscript.echo "ReturnValue: " & objOutParams.ReturnValue
Summary
You can further delve into the classes of WMI and design your own application to manage
almost every important aspect of the Windows OS. If you extend your skills to ASP.NET, then
you can develop a web application which can manage your server information on the fly, without
your presence in the office itself! I think you can imagine the same, if you further extend it to
the Pocket PC level! Good luck.
Anyway, once again, I must be thankful to all the readers who appreciated and encouraged me to
further expand the series in a much more useful and efficient manner. Thank you very much.
Any comments, suggestions, bugs, errors, feedback etc. are highly appreciated at
jag_chat@yahoo.com.