WMI Programming with Visual Basic.NET: Tips and Tricks

In my previous article, part four of this series, we looked into managing OS using WMI methods. In this article, we will look into some tips and tricks for using WMI.

Contributed by
Rating: 5 stars5 stars5 stars5 stars5 stars / 8
July 19, 2005
Rate this Article:
MEH MEH++


SEARCH ASP FREE
TOOLS YOU CAN USE

advertisement


You can download the zip of entire Visual Studio.NET solution (developed for this article) here.

The first part of my series gives you the details for creating a Visual Studio.NET solution for WMI from scratch.  It will not be repeated anymore in any of the future articles in this series.

Can we start another application (process) through WMI?

In all of my examples in the previous part, we worked with windows services (or system services). Now I will start talking about processes. A process is something like a thread which starts execution in its only memory area (application domain). In general, every application starts in the form of a process. Almost all processes can be viewed using the task manager. Some processes may be system processes which run in the background (without having a user interface). Every process gets identified by a process id internally.  We can get the full list of processes by using WMI class “Win32_process”. You can refer to part three to get an entire example of listing processes.

Now, the question is, can we start our own process (or even an application) using WMI? I hope anyone who works with .NET would definitely know how to do it using the native .NET framework. But now, I would like to do the same thing using WMI. The following program fragment demonstrates this:

' Get the object on which the method will be invoked

       DimprocessClassAsNewManagementClass("Win32_Process")

       ' Get an input parameters object for this method

       DiminParamsAsManagementBaseObject = processClass.GetMethodParameters("Create")

       ' Fill in input parameter values

        inParams("CommandLine") = "calc.exe"

       ' Execute the method

       DimoutParamsAsManagementBaseObject = processClass.InvokeMethod("Create", inParams,Nothing)

       DimobjAsObject= outParams("ReturnValue")

       Ifobj.ToString <> "0"Then

            MessageBox.Show("Could not Start, Returned code:" & obj.ToString)

       EndIf

A brief explanation of above program is included below.

We create a new process by using WMI class “Win32_Process”. There exists a method “create” within the class “Win32_Process”. That method creates a process at the OS through WMI and not our application. We provide parameters to that object using "inParams" (such as which application to execute as part of the process).

We execute the “create” method using the “InvokeMethod” of the “ManagementClass” object (currently the object points to a new process). The result of the “InvokeMethod” is returned into “outParams”. If the result is zero, it has successfully managed to invoke an external process. A non-zero result is a failure which would be shown through a message box. A detailed explanation of every return code is provided in the WMI SDK documentation.

You can understand the above program very easily, if you go through my previous article (part four).  All information about calling a WMI method (including the “InvokeMethod” member) was discussed in detail in that article. 

Retrieving all properties of a WMI class without knowing their names

In all of my previous parts of this series, I specified the properties I wanted to display manually. In order to do that, we should check with the WMI SDK documentation to get the full list of properties (and of course descriptions) of a particular WMI class. Now, is there any way to display all the properties at one time?

The answer is yes. We do have a way to display all the properties (along with values) of almost any WMI class dynamically. Before we implement it practically, I need to introduce two of the new classes of the “System.Management” namespace:

  • PropertyDataCollection
  • PropertyData

Using the “Properties” property of the “ManagementObject” class, we transfer all properties (along with values) to an object reference of type “PropertyDataCollection”. We extract each and every property of information from “PropertyDataCollection” by using “PropertyData”.  The following program illustrates the same. 

DimdtAsNewDataTable

        dt.Columns.Add("Name")

        dt.Columns.Add("Value")

       DimdiskAsNewManagementObject("Win32_LogicalDisk.deviceid='c:'")

       DimdiskPropertiesAsPropertyDataCollection = disk.Properties

       DimdiskPropertyAsPropertyData

       ForEachdiskPropertyIndiskProperties

           DimdrAsDataRow = dt.NewRow

            dr("Name") = diskProperty.Name

            dr("Value") = diskProperty.Value

            dt.Rows.Add(dr)

       NextdiskProperty

        dt.AcceptChanges()

       Me.DataGrid1.DataSource = dt

The above program gets all of the properties along with their values into a data table, and finally gets them displayed through a data grid.  The next section gives you a detailed explanation of the above program.

How does the program work?

Let me explain the above program line by line. 

DimdtAsNewDataTable

        dt.Columns.Add("Name")

        dt.Columns.Add("Value")

The above set of statements prepare a data table (for storing all properties with their values) with only two columns, namely “Name” and “Value”. 

DimdiskAsNewManagementObject("Win32_LogicalDisk.deviceid='c:'")

The above statement retrieves only a single instance of the “Win32_LogicalDisk” class based on the filter ‘deviceID=c:’. This excludes the use of unnecessary objects of type “ManagementObjectCollection”, as we are working with only a single instance.

DimdiskPropertiesAsPropertyDataCollection = disk.Properties

The above statement retrieves all properties along with all values using “disk.Properties” and stores them in the “diskProperties” object.

       DimdiskPropertyAsPropertyData

The above statement declares “diskProperty” to access each and every property from “diskProperties” collection.

ForEachdiskPropertyIndiskProperties

           DimdrAsDataRow = dt.NewRow

            dr("Name") = diskProperty.Name

            dr("Value") = diskProperty.Value

            dt.Rows.Add(dr)

       NextdiskProperty

The above loop iterates through each and every property existing in the “diskProperties” collection using “diskProperty” and assigns property information to a new individual data row, which finally gets added to the data table.

        dt.AcceptChanges()

The above statement ensures that the data table is filled with all of the contents from memory.

       Me.DataGrid1.DataSource = dt

The above statement displays all of the information available in the data table through a data grid.

How can we extend the above program to work with all objects?

The above example demonstrates working with only one instance. How can I work with more than one instance simultaneously? In other words, I would like to have each of the device details presented as a single row of information (columns being all the properties and not the rows, as demonstrated previously).

It is not a different concept, from the WMI point of view. It is just our logic as to how it is implemented. In the previous example, we added property information as a row. Now all the property names should be the columns of the data table. We need to retrieve the instances of logical devices and present them in different rows of the same data table (separated with property values as column values). The following program example gives an idea of the approach.

'preparing data table structure

       DimdtAsNewDataTable

       DimdiskAsNewManagementObject("Win32_LogicalDisk.deviceid='c:'")

       DimdiskPropertiesAsPropertyDataCollection = disk.Properties

       DimdiskPropertyAsPropertyData

       ForEachdiskPropertyIndiskProperties

            dt.Columns.Add(diskProperty.Name)

       NextdiskProperty

       'populating with rows

       DimsearcherAsNewManagementObjectSearcher("SELECT * FROM Win32_LogicalDisk")

       DimdisksAsManagementObjectCollection = searcher.Get()

       ForEachdiskIndisks

           DimdrAsDataRow = dt.NewRow

            diskProperties = disk.Properties

           ForEachdiskPropertyIndiskProperties

                dr(diskProperty.Name) = diskProperty.Value

           NextdiskProperty

            dt.Rows.Add(dr)

       Next

       'displaying

        dt.AcceptChanges()

       Me.DataGrid1.DataSource = dt

Even though, the above program looks bit lengthy, it is very simple to understand. The next section is dedicated to a detailed discussion of the above program.

How does this program work?

The program can be divided into three parts, for our convenience. The first part deals with preparing the structure (columns of properties) of the data table. The second part fills the data table with all of the information of logical disks. Finally, the third part displays the information back to the form.

The following can be considered the first part:

DimdtAsNewDataTable

       DimdiskAsNewManagementObject("Win32_LogicalDisk.deviceid='c:'")

       DimdiskPropertiesAsPropertyDataCollection = disk.Properties

       DimdiskPropertyAsPropertyData

       ForEachdiskPropertyIndiskProperties

            dt.Columns.Add(diskProperty.Name)

       NextdiskProperty

The above fragment is almost similar to that of the first program we discussed. The main goal of the above fragment is to create columns of the data table. The columns should be the property names themselves. To retrieve the property names, we need to connect to at least one logical device (which would definitely be present). I am connecting to ‘c:’ in this case. Using the FOR loop, I am retrieving all property names and adding them as columns to the data table.

The following is the second part:

       'populating with rows

       DimsearcherAsNewManagementObjectSearcher("SELECT * FROM Win32_LogicalDisk")

       DimdisksAsManagementObjectCollection = searcher.Get()

       ForEachdiskIndisks

           DimdrAsDataRow = dt.NewRow

            diskProperties = disk.Properties

           ForEachdiskPropertyIndiskProperties

                dr(diskProperty.Name) = diskProperty.Value

           NextdiskProperty

            dt.Rows.Add(dr)

       Next

If you carefully observe the above fragment, we are using nested loops. The outer loop works on each logical disk, and the inner loop works with the properties of the current logical disk of the outer loop.  This fragment is almost similar to the examples I provided in part three, except that I am using an inner loop. The inner loop actually assigns the information about all of the properties (of a particular disk) to a data row, which gets added to the data table.

And I hope you can understand the following third part very easily.

       'displaying

        dt.AcceptChanges()

       Me.DataGrid1.DataSource = dt

The above just ensures that data table is filled. It finally gets displayed using a data grid.

blog comments powered by Disqus
VISUAL BASIC.NET ARTICLES

- Basic Form Properties and Modality in VB.NET
- Multiple Document Interfaces in Visual Basic
- Visual Basic for Beginners
- ASP.NET Image to PDF with VB.Net
- MySQL in ASP.NET: Mono using VB.NET
- AsyncFileUpload File Type and File Size Vali...
- Visual Studio: Adding Functionality and Style
- Clocks and Countdowns
- User-defined Functions using Visual Basic Ap...
- Understanding Object Binding in VBA
- Mastering the Message Box
- Testing a Windows Forms Application
- Using Visual Basic.NET Features to Code a Wi...
- Correcting Code in a Windows Forms Applicati...
- Write Readable Code and Comments for Windows...

ASP Web Hosting ASP.Net Web Hosting Windows Web Hosting
ASP Free Forums 
 RSS  Tutorials RSS
 RSS  Forums RSS
 RSS  All Feeds
Site Map 
Request Media Kit
Write For Us Get Paid 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Privacy Policy 
Support 


© 2003-2012 by Developer Shed. All rights reserved. DS Cluster 6 - Follow our Sitemap
Most Popular Topics
All ASP.Net Tutorials