Article Options
Premium Sponsor
Premium Sponsor

 »  Home  »  .NET Framework  »  WMI connections made easy in VB.NET  »  WMI Queries
WMI connections made easy in VB.NET
by Martin de Klerk | Published  04/24/2005 | .NET Framework | Rating:
WMI Queries

A note on WMI queries: the WMI Query Language (WQL) is modelled after SQL, and as such supports extending clauses like WHERE, WITHIN, HAVING etc. For instance, to retrieve the WMI representation of a selected printer on a remote computer, you could issue a query like "Select * From Win32_Printer Where Name=""hpdeskjet""". Executing this query should result in an ManagementObjectCollection containing a single ManagementObject representing the selected printer.

Enter O.S. dependency. When running Windows 9.x or ME, the extended WQL clauses like WHERE are not supported. In this case the only option is to retrieve all printer objects and select the correct WMI object by code:

    WmiQueryResult = myConn.ExecWmiQuery("Select * From Win32_Printer")
    For Each WmiObject In WmiQueryResult
        If WmiObject.GetPropertyValue("Name") = "hpdeskjet" Then
            '
            '
        End If
    Next

Yet More Pitfalls

I had to work my way through the WMI information-jungle with a machete. For every working VBScript/WBEM/C++ solution found on the internet, my determination to solve the problem on hand in VB.NET grew. During this ordeal I found many promising (WMI) pathways towards my goals, but in many cases I had to abandon that trail half-way due to O.S. dependencies having only a XP Pro client at my disposal.

Another point is managed vs. unmanaged code. In above sample the WmiObject is of type Win32_Printer. This WMI object gets it's properties derived from various WMI subsystems, like it shows in MSDN's definition of the Win32_Printer.Caption property:

Caption
    Data type: string
    Access type: Read-only
    Qualifiers: MaxLen(64)

Short description of an object, a one-line string. This property is inherited from CIM_ManagedSystemElement.

I discovered that many WMI properties were not available, as those were unmanaged code/data . Although disappointing, in .NET that makes sense. But it also restricted me by default to the use only those properties that were either WMI intrinsic, generic to the handled WMI object (no inheritance) or properties that were inherited from the CIM_ManagedSystemElement class.

For accessing unmanaged WMI code or data, check out the links provided at the end of this article.

An Added Bonus (or Two)

So why call the method .Poll() and not .Connect() ?
There are several reasons for this.

The first one being that the necessity for this class originated out of creating a network printer monitor program. The program had to be able to detect when a remote computer came on-line, and if so, automatically create the WMI connection to start querying the remote printers.

The second reason was that the ConnectionTester class was original intended to speed up the connection process. If a remote computer was not on-line, there was no reason to initiate a WMI connection which would take a considerable amount of time before throwing an exception. For the same reason the WMI availability check was to be performed only on the first time the remote was detected on-line.

The third reason is OS dependency. As certain WMI features and classes are only available under specific Windows versions, I needed an easy way to identify the version of Windows running on the remote computer. This is done by the Sub GetRemoteOsInfo() which is ( oh sweet irony!) totally OS dependent. Just check out the source code and you'll see what I mean.

The way the code is set up, you can use the ConnectionTester class for a more general use:

Bonus #1: You can switch off the WMI functionality of the ConnectionTester class, so it will perform only a quick online test. This, together with the addition of a Timer, enables you to build a simple connection monitor program. Just set .WmiCheck to False, load .ServerName with "www.vbcity.com", and in the Timer.Tick event ( or Timer.Elapsed event, depending on which Timer class you're using) simply place the following statements:

    WmiConn.Poll()
    If Not WmiConn.IsOnline Then
        Console.WriteLine("VBCity unavailable. " _
          & "Please switch to PANIC MODE and dial 911.")
    End If

Now, of course the VBCity server is not WMI enabled. But if it were the case, you should have no problem with retrieving WMI information over the Internet using the ConnectionTester class. That makes Bonus #2: Whether you need to manage WMI objects locally, on a computer in a LAN or a computer somewhere in this world connected to the Internet, it is completely transparent using the ConnectionTester class.

Comments    Submit Comment

Comment #1  (Posted by an unknown user on 07/13/2005)
Rating
This article is great. Easy to read and understand. It gave me everything I needed.
 
Comment #2  (Posted by an unknown user on 07/22/2005)
Rating
This is a good starter. Luckily, you provide the links to the downloads at the end of the article. It's perhaps a good idea to provide them inside the text as well.
 
Comment #3  (Posted by an unknown user on 07/29/2005)
Rating
It is perfect
 
Comment #4  (Posted by an unknown user on 08/02/2005)
Rating
After days of crawling the net, this is the most professional article found yet on WMI & remote connectivity.

WELL DONE !
 
Comment #5  (Posted by an unknown user on 08/02/2005)
Rating
After days of crawling the net, this is the most professional article found yet on WMI & remote connectivity.

WELL DONE !
 
Comment #6  (Posted by an unknown user on 08/24/2005)
Rating
Great approach to introducing people to WMI. Simple to read and understand. Great Job.
 
Comment #7  (Posted by an unknown user on 09/01/2005)
Rating
Found exactly what I needed to fix my code. Thanks
 
Comment #8  (Posted by an unknown user on 10/06/2005)
Rating
This is a great job. In my case help me to resolve a problem with network server monitoring. Thanx for all.
 
Comment #9  (Posted by an unknown user on 10/17/2005)
Rating
Nice and simple.
 
Comment #10  (Posted by an unknown user on 11/12/2005)
Rating
Impeccably presented.
 
Comment #11  (Posted by an unknown user on 12/01/2005)
Rating
It is what I need to use WMI. And the links is useful for me
 
Comment #12  (Posted by an unknown user on 12/02/2005)
Rating
Excellent article. Very well written.
 
Comment #13  (Posted by Andy Bonner (aka Skullcrusher) on 12/04/2005)
Rating
Just found another port that needed to be allowed on XP SP2.

TCP Port 1038 - Message Tracking Query Protocol
 
Comment #14  (Posted by Benjamin Lindelof on 12/09/2005)
Rating
Unable to follow the author.
 
Comment #15  (Posted by an unknown user on 12/09/2005)
Rating
No method to read the Arrays in WMI?
 
Comment #16  (Posted by an unknown user on 12/09/2005)
Rating
No method to read the Arrays in WMI?
 
Comment #17  (Posted by Benjamin Lindelof on 12/09/2005)
Rating
I found the bug. Instead of:
myManagementScope = New System.Management.ManagementScope("\" & _
It should say:
myManagementScope = New System.Management.ManagementScope("\\" & _

 
Comment #18  (Posted by an unknown user on 12/12/2005)
Rating
The article is very good. However, I can't figure out how to download the code. I have searched the following page and can't find the word "download" or anything tat looks like a download link for the ConnectionTester referenced on page 5 of the article:

http://www.devcity.net/Articles/144/6/article.aspx

Thanks!
 
Comment #19  (Posted by an unknown user on 12/12/2005)
Rating
The article is very good. However, I can't figure out how to download the code. I have searched the following page and can't find the word "download" or anything tat looks like a download link for the ConnectionTester referenced on page 5 of the article:

http://www.devcity.net/Articles/144/6/article.aspx

Thanks!
 
Comment #20  (Posted by an unknown user on 12/25/2005)
Rating
Many thanks, you saved me a lot of time (and maybe grey hairs ^^)!
 
Comment #21  (Posted by an unknown user on 12/25/2005)
Rating
To look at additional WMI classes, see the wbemtest.exe tool located on any system with WMI installed. Just goto Start --> Run, then type "wbemtest", then connect to the "root\cimv2" (or a different) namespace, click Enum Classes --> Recursive!
 
Comment #22  (Posted by Bhaskar on 01/20/2006)
Rating
Thanks for the fruitful efforts made !

This code works very well when the servername/IP Address is "localhost"/127.0.0.1

When i give Servername as one of the systems in the LAN it gives:
"Connecting to {0}DevServer{0}DevServer is online with IP address: {1}192.168.1.25.Error while connecting to {0}DevServer: {1}Access denied"

This is the case with all the systems in my LAN.
Please help!!!
 
Comment #23  (Posted by an unknown user on 01/21/2006)
Rating
Either I am blind or there is no link to download this code. I am exited about it, but am also frustrated that I cannot download it :(
 
Comment #24  (Posted by Kevin on 01/29/2006)
Rating
Why is there no remoting example using early binding. All that is said is that mgmtclassgen.exe can be used to make WMI strongly typed.
 
Comment #25  (Posted by an unknown user on 02/02/2006)
Rating
great
 
Comment #26  (Posted by an unknown user on 02/11/2006)
Rating
Well, I was looking for this information and, wow, I found much more than I expected. Great job! Hopefully your grey hair turn back! ;)
 
Comment #27  (Posted by an unknown user on 03/09/2006)
Rating
just easy too read - keep on goin'
 
Comment #28  (Posted by an unknown user on 03/09/2006)
Rating
Excellent tutorial! The download is difficult to find, but not the authors fault. Works great. There is one mistake in the first page example as mentioned already, missing a \. Should be \\. Anyway, great stuff, the class is awesome!
 
Comment #29  (Posted by an unknown user on 03/13/2006)
Rating
I find this article easy to understand, it's perfect for a beginner like me searching to get the best from WMI
 
Comment #30  (Posted by an unknown user on 03/31/2006)
Rating
Felicitaciones.
Es un articulo facil de entender para los desarrolladores de otros idiomas.

Deben cambiar el link de:

WMI Administrative Tools (including CIM studio)

a:


http://www.microsoft.com/downloads/details.aspx?FamilyID=6430f853-1120-48db-8cc5-f2abdc3ed314&DisplayLang=en

Oscar José Lofrano Maturi
ojlofranom@msn.com
MCP VB.NET Windows Application
Venezuela
 
Comment #31  (Posted by Someone on 04/18/2006)
Rating
Great article! But there is a bug in the function ExecWmiQuery ;) It does not work for a remote Win2003 machine that requires login. Instead of

_ManagementSearcher = New System.Management.ManagementObjectSearcher(_ManagementScope.Path.ToString, cWmiQuery) ' bug: this will cause a new ManagementScope object to be created, when the correct ManagementScope object already exists

Use:

Dim query As New ObjectQuery(cWmiQuery)
_ManagementSearcher = New System.Management.ManagementObjectSearcher(_ManagementScope, query)

Your code creates a new instance of ManagementScope and does not set the UserName and Password connection options. Instead use the existing _ManagementScope variable which does have the username and password set already! :)

 
Comment #32  (Posted by an unknown user on 04/20/2006)
Rating
A superb article to newbies of WMI like me but i want more info for remote connections,that code wont work in XP Machines and Server 2003
 
Comment #33  (Posted by an unknown user on 05/09/2006)
Rating
interesting
 
Comment #34  (Posted by Stuart Nathan on 06/27/2006)
Rating
When I run your example, I get the error message "RPC Server is unavailable" when I try to connect to another machine.
 
Comment #35  (Posted by an unknown user on 06/30/2006)
Rating
Very interesting article about the link between scripting & vb.net.Tnx!
 
Comment #36  (Posted by an unknown user on 07/06/2006)
Rating
Excelentemente explicado. De mucha utilidad y muy claro.
 
Comment #37  (Posted by an unknown user on 07/23/2006)
Rating
Very well written article. Easy to follow and informative. Thank you.
 
Comment #38  (Posted by an unknown user on 07/26/2006)
Rating
Easy to read, easy to understand.
Great article for someone starting out!
 
Comment #39  (Posted by sovannborith on 08/17/2006)
Rating
my computer does not have system.Management namespace. how can i get it. please reply

 
Comment #40  (Posted by an unknown user on 08/19/2006)
Rating
Breath of fresh air on the subject. I only wish that my web searches hit on the article sooner.
 
Comment #41  (Posted by an unknown user on 10/05/2006)
Rating
Great Job!! Thanks a lot
 
Comment #42  (Posted by Muhammad Aamir Hassan on 10/11/2006)
Rating
i really enjoyed this snipt. May God help you

aamir
 
Comment #43  (Posted by Lesh Augustus on 11/02/2006)
Rating
Set System Information or Set System Environment Variable in VB.Net
===================================================

Dim objEv As ManagementObjectSearcher = New ManagementObjectSearcher("SELECT * FROM Win32_Environment")
For Each objMgmt As ManagementObject In objEv.Get
If objMgmt("Name") = "Path" And objMgmt("UserName") = "" Then
Dim strPath As String = objMgmt("VariableValue")
If strPath.ToLower.IndexOf("cvsnt") >= 0 Then
If objMgmt("VariableValue").ToString.Substring(objMgmt("VariableValue").ToString.Length - 1) = ";" Then
objMgmt("VariableValue") = objMgmt("VariableValue") + Trim(txtNewPath.Text) + ";"
Else
objMgmt("VariableValue") = objMgmt("VariableValue") + ";" + Trim(txtNewPath.Text) + ";"
End If
End If
objMgmt.Put()
MessageBox.Show("Path Added Successfully")
End If
Next
 
Comment #44  (Posted by PK on 12/22/2006)
Rating
Hi, I couldn't find the link to the ConnectionTester class?
 
Comment #45  (Posted by an unknown user on 03/12/2007)
Rating
Thanks buddy, very good article
 
Comment #46  (Posted by zmrcic on 03/14/2007)
Rating
I'm using wmi and I think its great article. I have new problem. Can I look into printer setup (emulation, characteset....) by wmi?
 
Comment #47  (Posted by an unknown user on 05/25/2007)
Rating
Hi Mr. Martin

Great article! But could you help me with the Access is Denied error? i'm trying to connect to a remote computer and it returns an online status but i can't access it. I think it's the rpc or something. AT CheckForWMI procedure, the error is in the else statement of the code below.

Catch e1 As Exception
'* USUALLY indicates remote RPC server is not online
If e1.Message.IndexOf("RPC-server") <> -1 Then
'* Do not set _HasErrors in this case
'* as that could be interpreted as being off-line
_ErrorMessage = e1.Message
Else
_HasErrors = True
_ErrorMessage = e1.Message
End If

i really need help please!
thanks!!
 
Comment #48  (Posted by Ashu on 10/09/2007)
Rating