An in-depth look at WMI and instrumentation, Part II

Introduction

The first part of this article explained how to instrument your application.We looked at a simple WMI provider to demonstrate how to define WMI classes,how the .NET framework registers these classes in the WMI store, how topublish class instances and how to raise WMI events. On the other hand welooked at a simple WMI consumer to demonstrate how to query for WMI classinstances and how to subscribe to and receive asynchronously WMI events.Finally we looked at Microsoft Operations Manager 2005, how to set it up tomonitor WMI events raised by instrumentation applications and how to createManagement Packs to distribute to customers. This gives a comprehensive viewabout how to instrument applications and how to tie this in with managementapplications like MOM 2005.

This second part looks in more detail at how to query the WMI store, how towork with WMI classes and class instances, and then demonstrates the wealthof information available through the Win32 and IIS WMI providers. Thisarticle has two sample applications attached. The "WMI System Browser"allows you to browse a wealth of information about your machine. The "WMIPowerBrowser" allows you to browse the WMI schema and look in detail at classesandclass instances. All .NET types for working with WMI reside in theSystem.Management DLL, so you need to add the System.Management namespace toyour code.

 

Working with WMI namespaces

WMI supports namespaces, allowing users to logically group WMI classestogether. Each WMI provider normally registers its own WMI namespace andthen all its classes within that namespace. For example, all Win32 WMIclasses can be found in the namespace "root\cimv2", all IIS WMI classes canbe found at "root\microsoftiisv2", and all LDAP WMI classes can be found at"root\directory\ldap". The root namespace is called "Root" and namespacescan have child namespaces and WMI classes. Each namespace contains a classcalled __namespace and its class instance list gives you a list of all childnamespaces. Here is a code snippet for that:

 

// the root namespace we are connecting to
ManagementScope Scope = new ManagementScope(@"\.\Root");

// the __namespace class to connect to -which provides a list of
// all child namespaces in the namespace we are connecting to
ManagementPathClassPath = new ManagementPath("__NAMESPACE");

// connect to the namespace and class
ManagementClassWMIParentObject = new ManagementClass(Scope, ClassPath, null);

try
{
      // now loop through all the object instances we find for thatnamespace class
      foreach (ManagementObject WMIChild in WMIParentObject.GetInstances())
      {
            // a child-namespace found
            string ChildNamespace = Convert.ToString(WMIChild.Properties["Name"].Value);
           
            // add the namespace name to thetree view
            TreeNodeCol.Add(WMIChild.Path.Path, ChildNamespace.ToLower());
           
            // release the underlying COMobject
            WMIChild.Dispose();
      }
}

// show any exception happening
catch (Exception e)
{
      MessageBox.Show(e.Message);
}

// release the underlying COM object
finally
{
      WMIParentObject.Dispose();
}

It first creates a ManagementScope object and sets it to the root namespaceon the local machine. This defines where (which machine and namespace) theclass we are binding to is residing. Next we create a ManagementPath settingit to the WMI class we are binding to (the __namespace class). Finally wecreate a ManagementClass object using the scope and path object we created.The same could be achieved by only creating a ManagementClass object andpassing along the path "\.\root:__namespace". When you have bound to a WMIclass, you can call GetInstances() to get a list of all class instancesfor this class. In the case of the __namespace class this is the list ofchildnamespaces. The path and the name of each namespace is then used to add itto a tree view. The ManagementClass and ManagementObject classes useunderlying unmanaged COM objects, so call Dispose to release them.

The WMI infrastructure allows you to apply security to each namespace. Openupthe "Computer Management" console in Windows (right click on "My Computer"and choose Managefrom the popup menu) and navigate to the item "Serviceand Applications" and then "WMI Control". Open up the properties of the "WMIControl" item and navigate to the "Security" tab. It allows you to navigatethe namespace hierarchy (shown in a tree view). Select the one you want toset the security for and click on the "Security" button. This brings up thestandard Windows ACL dialog and allows you to set the rights for eachWindows user orWindows group. The available rights are:

 

  • Execute Methods Allows user to execute methods defined on theWMIclasses.
  • Full Write
  • Edit Security information

This allows you to set granular access rights for the classes and classinstances in this namespace. The list of security rights shown is on Windows2003. On Windows XP, "Enable Account" is named "Enable" and "Full Write" isnamed "Full Control". All other security rights are named the same.

 

Working with WMI classes

The class ManagementClass allows you to bind to and work with WMI classes.The path of a WMI class consists of th
e machine, followed by the namespacehierarchy ending with a colon and the class name itself, for example"\.\Root\cimv2:Win32_Volume". The ManagementClass provides access to thefollowing information:

 

  • SystemProperties an array of strings.
  • __Dynasty example __SystemClass. This value is the same as __Derivation if the classinherited from has no parent class, such as the class __Provider(inherits from __SystemClass which has no parent class).
  • __Path
  • __Relpath which excludes the machine and namespace (this is everything after thecolon of the full path). In our example this is __Win32Provider.
  • __Namespace
  • __Server
  • __Property_Count

This collection is of the type PropertyDataCollection which is a collectionof PropertyData types. The type PropertyData exposes Name and Valueproperties. The propertyIsArray can be used to determine whether Value is an array of values ora single value.

 

  • Properties writing property values on a class instance. This is also of the typePropertyDataCollection, which is again a collection of PropertyData types.

     

  • Qualifiers href="http://msdn.microsoft.com/library/en-us/wmisdk/wmi/wmi_qualifiers.asp">here. Some examples are:

     

    • Abstract
    • Dynamic .NETinstrumentation (see part I of this article) are marked dynamic.
    • Provider
    • Singleton

      This is a collection of the type QualifierDataCollection which is acollection of QualifierData types which exposes Name and Value properties toread the name and value of the qualifier.

       

    • Methods A collection of methods defined by this WMI classwhich can be invoked by class instances. This collection is of the typeMethodDataCollection which is a collection of MethodData types. TheMethodData type exposes a Name property for the method name andInParameters and OutParameters propertieswhich provide access to all in and out parameters of the method.InParameters and OutParameters are of the type ManagementBaseObject. Theyhave a "Properties" property, of type PropertyDataCollection which is acollection of the type PropertyData, providing access to each individual inor out parameter. You can read the name, the value, check if it is an arrayof values or a single value, etc. The returnvalue of the method is an out parameter with the name ReturnValue.

    These four collections provide you with a wealth of information about theWMI class. They can be used to read information about a WMI class and alsoto edit a WMI class (shown by the attached "WMI Power Browser" application).Here is a code snippet illustrating how to read class information.

     

    ManagementClass WMIClass = null;

    try
    {
          WMIClass = new ManagementClass(@"\.\root\cimv2:__Win32Provider");
         
          // add all the properties to the list
          foreach (PropertyData Property in WMIClass.Properties)
                ListCollection.Add(new ListViewItem(new string[] { "Property",
                                   Property.Name,GetPropertyValue(Property) }));
         
          // add all the system properties to the list
          foreach (PropertyData Property inWMIClass.SystemProperties)
                ListCollection.Add(new ListViewItem(new string[] { "SystemProperty",
                                   Property.Name,GetPropertyValue(Property) }));
         
          // add all the qualifiers to the list
          foreach (QualifierData Qualifier inWMIClass.Qualifiers)
                ListCollection.Add(new ListViewItem(new string[] { "Qualifier",
                                   Qualifier.Name, Convert.ToString(Qualifier.Value) }));
         
          // add all the methods to the list
          foreach (MethodData Method inWMIClass.Methods)
                ListCollection.Add(new ListViewItem(new string[] { "Method",
                                   Method.Name, String.Empty }));
    }

    // show any exception happening
    catch (Exception e)
    {
          MessageBox.Show(e.Message);
    }

    // release the underlying COM object
    finally
    {
          if (WMIClass != null)
                WMIClass.Dispose();
    }

    This code snippet binds to the __Win32Provider class in the root\cimv2namespace and then reads all its properties, system properties, qualifiersand methods and
    adds for each the name and value to a list view (note thatmethods have no values). At the end it calls Dispose to release theunderlying COM object. The value of properties or system properties can bearrays so it calls GetPropertyValue() which does the following:

     

    public string GetPropertyValue(PropertyData Property)
    {
          // a single value property so we return its value as string value
          if (!Property.IsArray)
                return Convert.ToString(Property.Value);
         
          // return a comma separated list of array values
          else
          {
                string PropertyValue = String.Empty;
               
                // loop through all items in the array; only if we have items (!= null)
                if (Property.Value != null)
                {
                      foreach (object Value in ((Array)Property.Value))
                            PropertyValue += Convert.ToString(Value) + ", ";
                }
               
                // return the comma separated listof values for this array
                if (PropertyValue.Length >0)
                      returnPropertyValue.Substring(0, PropertyValue.Length – 2);
                else
                      return String.Empty;
          }
    }

    It checks through IsArray if this is an array or single value. If a singlevalue it converts the value to a string and returns it. For an array ofvalues it loops through each item and adds it to a comma-separated listwhich is then returned.

     

    Working with WQL queries

    You can query WMI using the WQL query language. WQL is based on the standardSQL syntax with some differences, the biggest one being that it allows onlyqueries and not updates, inserts or deletes. It allows you to queryfor classes, class instances, class associations, inherited classes,etc. Queries are always executed against a namespace. Here are a fewexamples:

     

    • SELECT * FROM meta_class
      Queries for all classes in the namespace.

       

    • SELECT * FROM meta_class WHERE __CLASS = "Win32_Volume"
      Queries for a class with the name Win32_Volume.

       

    • SELECT * FROM meta_class WHERE __this ISA "Win32_Volume"
      Queries for a class with the name Win32_Volume and all its child classes. Soany class which directly or indirectly is inherited from this class isreturned.

       

    • SELECT * FROM Win32_Volume WHERE __CLASS = "Win32_Volume"
      Queries for any class instances of the class Win32_Volume.

       

    • SELECT * FROM Win32_Volume
      Queries for any class instances of the class Win32_Volume and any otherclass directly or indirectly inherited from it.

    To execute a WQL query create first a ManagementScope object which definesagainst which namespace you want to perform this query, for example"\.\root\cimv2". Next create an instance of WqlObjectQuery and pass alongthe query WQL string. Finally create an instance of ManagementObjectSearcherand pass along the scope and query objects. CallManagementObjectSearcher.Get() which performs the search and returns acollection of ManagementObject objects. Here is a sample code snippet:

     

    // the namespace we are searching in
    ManagementScope Scope = new ManagementScope(@"\.\root\cimv2");

    // the query we are performing
    WqlObjectQuery Query= new WqlObjectQuery("SELECT * FROM meta_class");

    // enumeration options to use for the search; set a time-out value
    EnumerationOptionsOptions = new EnumerationOptions();
    Options.Timeout = new TimeSpan(0, 0, 10);

    // instantiate the searcher object using the scope and query
    ManagementObjectSearcher Searcher = new ManagementObjectSearcher(Scope, Query, Options);

    try
    {
          // now get the search results and loop through all found objectinstances
          foreach (ManagementObject Object inSearcher.Get())
          {
                // add the object to the listview
                Collection.Add(new ListViewItem(new string[] { Object.Path.Path,
                &nbsp
    ;          
       Object.Path.RelativePath } ));
               
                // dispose the object instance
                Object.Dispose();
          }
    }

    // show any exception happening
    catch (Exception e)
    {
          MessageBox.Show(e.Message);
    }

    // dispose the underlying search COMobject
    finally
    {
          Searcher.Dispose();
    }

    This code snippet sets the search scope to the namespace "root\cimv2" andsearches for all classes in that namespace. It also sets a timeout of 10seconds for enumerating the result-set, not for how longthe actual search is allowed to take. It adds for each found object the fulland relative path to a list view. Don't forget to call Dispose() on eachobject in the enumeration and on the ManagementObjectSearcher object toreleasethe underlying COM objects.

    You can also build associations between different classes using associationclasses. Association classes are classes which have references to two otherclasses and through that associate these two classes. The diagram belowshows the associations between the Win32_DiskPartition class with theWin32_ComputerSystem, Win32_DiskDrive and Win32_LogicalDisk class. For eachthere is an association class:

    WMI Class Associations An in depth look at WMI and instrumentation, Part II
    • Win32_SystemPartitions computer system. The GroupComponent property on this class contains thereference to the Win32_ComputerSystem class while the PartComponent propertycontains the reference to the Win32_DiskPartition class.
    • Win32_DiskDriveToDiskPartition partition. The Antecedent property on this class contains the reference tothe Win32_DiskDrive class while the Dependent property the reference to theWin32_DiskPartition class.
    • Win32_LogicalDiskToPartition a partition. The Dependent property on this class has the reference to theWin32_LogicalDisk class and the Antecedent property the reference to theWin32_DiskPartition class.

    WMI allows you to query for those associated classes and the associationclasses which reference the two classes together. This makes it easy to findall associations and association classes without having to go through thedocumentation of all classes, which in the case of "root\cimv2" number inthehundreds. Let's assume your computer has an instance of theWin32_DiskPartition class with the value "Disk #0, Partition #0" and youwant to find all associated classes and class instances and associationclasses and class instances. Here is how it works:

     

    • ASSOCIATORS OF {Win32_DiskPartition.DeviceID="Disk #0, Partition#0"}
      Returns all class instances which are associated with thisWin32_DiskPartition class instance. The result may vary based on yourhardware and software configuration. My machine returns an instance of theWin32_ComputerSystem class (value Enterprise-Minds), an instance of theWin32_LogicalDisk class (value "C:") as well as an instance of theWin32_DiskDrive class (value "\.\PHYSICALDRIVE0"). Note thatWin32_DiskDrive is your physical disk drive while Win32_LogicalDiskDrive isthe logical disk created through your OS.

       

    • ASSOCIATORS OF {Win32_DiskPartition.DeviceID="Disk #0, Partition #0"}WHERE ClassDefsOnly
      This query returns the WMI class names of all the classes associated withthe Win32_DiskPartition class. My machine returns Win32_ComputerSystem,Win32_DiskDrive and Win32_LogicalDiskDrive.

       

    • REFERENCES OF {Win32_DiskPartition.DeviceID="Disk #0, Partition#0"}
      Returns all the association class instances which have a reference to thisWin32_DiskPartition class instance, meaning one of the properties contains areference to this class instance. My machine returns an instance of theWin32_DiskToDiskPartition class, an instance of the Win32_SystemPartitionsclass and an instance of the Win32_LogicalDiskToPartition class.

       

    • REFERENCES OF {Win32_DiskPartition.DeviceID="Disk #0, Partition #0"}WHERE ClassDefsOnly
      This query returns the class names of all the associations classesreferencing the Win32_Partitions class. My machine returnsWin32_DiskDriveToDiskPartition, Win32_LogicalDiskToPartition andWin32_ComputerSystem.

    WMI provides a wealth of information, so it is important to have strongquery/search capabilities and to be able to get a good view of theassociations between the data. WQL is build on top of SQL which makes thequery language instantly familiar to developers but is still enhanced tosupport WMI specific capabilities. You can find out more about WQL from here as well as here.

     

    Working with WMI class instances

    The ManagementObject class can be used to work with WMI class instances. TheManagementClass type is inherited from the ManagementObject type. This meansnearlyall the functionality explained in the section "Working with WMI classes"applies also to WMI class instances. The two exceptions are that theproperty values for a class are default values (if specified) while theyreturn the actual value for a class instance, and there is no Methodscollection, meaning there is no access to the method information. You canobtain the class information of a class instance through the ClassPathproperty. This returns a ManagementPath type which provides access to theclass name (ClassName property), the server queried (Server property), thenamespace (property NamespacePath), the full path (Path property) and therelative path (RelativePath property).

    Through ManagementObject.InvokeMethod() you can invoke a method on the classinstance. Managed WMI classes (i.e., those provided by managed code) cannotprovide methods. But many of the unmanaged WMI classes provide methods whichyou can invoke to manipulate the class instance. For example the classWin32_Volume has a Chkdsk() method to perform a check disk, aDefragAnalysis() method to perform defrag analysis, a Defrag() method toperform a defrag and many more. Query the WMI class to obtain a list ofmethods. When you know the method name use the methodManagementObject.GetMethodParameters() to obtain a ManagementBaseObject withthe list of in parameters for the method. Next set the values for all inparameters and then call ManagementObject.InvokeMethod() to invoke themethod. It returns another ManagementBaseObject type which contains thevalues of all the out parameters plus the method return value. The methodreturn value is stored in the out parameter list as an out parameter withthe name ReturnValue. Here is a code snippet:

     

    ManagementObject WMIObject = null;
    string ObjectPath =@"\.\root\cimv2:Win32_Proxy.ServerName=""Enterprise-Minds""";

    string
    MethodName ="SetProxySetting";

    try
    {
          // bind to the WMI object instance
          WMIObject = new ManagementObject(ObjectPath);
         
          // get a WMI object representing all in-parameters for this method
          ManagementBaseObject InParams =WMIObject.GetMethodParameters(MethodName);
         
          // set all the in-param values according to the in-param list view
          foreach (ListViewItem Item in InParamItems)
                InParams[Item.SubItems[0].Text] = Item.SubItems[1].Text;
         
          // set the method invoke options so that the method has 10 sec toexecute
          InvokeMethodOptions Opt = new InvokeMethodOptions();
          Opt.Timeout = new TimeSpan(0, 0, 10);
         
          // execute the method on the WMI object and get the out-parameters
          ManagementBaseObject OutParams =WMIObject.InvokeMethod(MethodName, InParams, Opt);
         
          // read all the return values and show them in the out-param list view
          foreach (PropertyData Property inOutParams.Properties)
                OutParamItems.Add(new ListViewItem(new string[] { Property.Name,
                                         GetPropertyValue(Property) }));
         
          // dispose the COM object of the in param object
          if (InParams != null)
                InParams.Dispose();
         
          // dispose the COM object of the out param object
          if (OutParams != null)
                OutParams.Dispose();
    }

    // show any error message
    catch (Exception e)
    {
          MessageBox.Show(e.Message);
    }

    // free up the underlying COM object
    finally
    {
          if (WMIObject != null)
                WMIObject.Dispose();
    }

    The code snippet first binds to the Win32_Proxy class instance (note thatEnterprise-Minds is the machine name, which will of course be different foryourmachine) and then gets the method in parameters from theGetMethodParameters() method. It then reads all the in parameter values fromthe InParamItems list view. Then it invokes the InvokeMethod() which returnsall the out parameters and the method return value. These are then added toan OutParamItems list view. At the end it calls Dispose on the in parameterand out parameter types and the class instance itself to release theunderlying COM objects. Note that some out parameter values might be anotherWMI class instance. The "WMI Power Browser" sample application attachedshows how to check for the type of the return value and then read theproperty values of such a returned WMI class instance.

    You can also delete class instances, unless they are dynamic. First bind tothe class instance and then call the method ManagementObject.Delete(). Hereis a code snippet for that:

     

    ManagementObject WMIObject = null;

    try
    {
          WMIObject = new ManagementObject(ObjectPath);
         
          // delete the object
          WMIObject.Delete();
    }

    // show any exception happening
    catch (Exception e)
    {
          MessageBox.Show(e.Message);
    }

    // release the underlying COM object
    finally
    {
          if (WMIObject != null)
                WMIObject.Dispose();
    }

    Property values of a class instance can be updated. These changes will notbe committed till you call ManagementObject.Put(). The provider for dynamicclass instances needs to support write access to the property. No managedclass instances support write access. Here is a code snippet showing how toupdate property values:

     

    ManagementObject WMIObject = null;

    try
    {
          WMIObject = new ManagementObject(ObjectPath);
         
          n style="color:green;"> // loop through all the properties in the list view and get thevalues
          foreach (ListViewItem Item in ItemCollection)
                WMIObject.Properties[Item.SubItems[0].Text].Value =Item.SubItems[1].Text;
         
          // write any changes back to the WMI store
          WMIObject.Put();
    }

    // show any exception happening
    catch (Exception e)
    {
          MessageBox.Show(e.Message);
    }

    // release the underlying COM object
    finally
    {
          if (WMIObject != null)
                WMIObject.Dispose();
    }

    This sample takes all the new property values from an ItemCollection listview. It first binds to the class instance and then loops through the listview, gets the latest values and updates the object property values with it.It then calls ManagementObject.Put() to commit the changes back to the WMIstore (or the provider for dynamic classes). At the end it again callsDispose() to free up the underlying COM object.

     

    The "WMI Power Browser" sample application

    This sample application demonstrates how to enumerate the list of WMInamespaces and all classes for each. It also demonstrates how to performqueries, whether querying for all the classes of a namespace, all classinstances of a class, all associated classes and class instances, allassociation classes or class instances, etc. It also allows you to enter aWQL query string and execute the query, showing its result set. This makesit easy to experiment with WQL and see right away the result set. The samplealso demonstrates how to create new classes, edit or delete new classes,clone class instances and edit or delete class instances. It also allows youtoview all the methods available on a class instance and then to invoke them.The rich Windows form interface (using tree views, list views, etc.) makesit very easy to discover all namespaces, classes and class instances. At thesame time you can step through the code and understand in all details how towork with WMI namespaces, classes and class instances.

     

    The "WMI System Browser" sample application

    This sample application shows how you can use WMI to find out a wealth ofinformation about any machine on your network. The "WMI System Browser"shows only a subset of information available through WMI. In the list on theleft side you can select a category, for example "processor information","BIOS information", "IIS web sites", etc. The list in the middle then showsyouall found instances, for example it shows each found processor, eachfound IIS web site, etc. Selecting a specific instance shows the details inthe list onthe right side, for example the maximum and current clock speedof a processor, the serial number and release date of the BIOS, etc. Clickon the "Show class description" button to launch the MSDN help page of theunderlying WMI class. This helps a lot to understand all the propertiesavailable on a class. If the class exposes methods then you can click on the"Invoke a method" button. It lists for you on the left side all availablemethods. Selecting a method shows you in the list in the middle all inparameters. You can set the values for each by clicking on it. Click on the"Invoke method" button to invoke the method and show the out parameters inthe list on the right side. Click on the "Show method description" to launchthe MSDN help page for the selected method. This helps to understand the inand out parameters of each method.

    It is very simple to extend the sample application and really understandwhat information WMI can provide. This could even be a simpletroubleshooting tool, helping the user understand the hardware and softwareconfigurationof a remote machine. Much of the information shown here can be useful whenresolving issues. Here is a list of information you can view, and which WMIclass is used for it:

     

    • IIsWebServiceSetting the IIS itself. This includes ASP settings, logging settings, authenticationsettings, etc.
    • IIsApplicationPoolSetting application pools (IIS 6.x specific). For each you can see the usercredentialsused, application pool recycling policy information, etc.
    • IIsWebServerSetting
    • IIsWebVirtualDirSetting
    • Win32_Battery
    • Win32_BIOS
    • Win32_ComputerSystem owner, the hardware model and manufacturer, etc.
    • Win32_ComputerSystemProduct hardware system including the serial number, name, vendor, version,etc.
    • Win32_DiskPartition Returns the created disk partitions (adisk partition may span multiple physical disks and contain multiple logicaldisks). For each you find the size, block size, number of blocks, etc.
    • Win32_Environment each you can see the name, value, if it is a system or user definedvariable, etc.
    • Win32_Group – Lists all the Windows groups of your local machineas well as of the domain, if connected to a domain. For each group you cansee the name, domain, SID, etc.
    • Win32_LogicalDisk system and for each the file system, the driver letter, the size and freespace, etc.
    • Win32_NetworkAdapterConfiguration configurations (not the physical network adapters). For each network adapterconfiguration you see the IP address, subnet mask, is it DHCP enabled,etc.
    • Win32_NTDomain (your local computer is returned as a domain too) and information like thename, domain controller address, etc.
    • Win32_OperatingSystem like build number, serial number, name, OS type, etc.
    • Win32_OSRecoveryConfiguration configuration including where to create the dump file, whether to autoreboot, etc.
    • Win32_PageFile including the file path, the file size, etc.
    • Win32_PhysicalMemory system and for each the capacity, speed, data width, etc.
    • Win32_PnPDevice
    • Win32_Printer sizes supported, etc.
    • Win32_Process
    • Win32_Thread For each thread it shows the total execution time and kernel time inmilliseconds, its priority and the process it belongs to, etc.
    • Win32_TimeZone your OS. Returns its name, daylight savings information, etc.
    • Win32_UserAccount machine as well as of the domain, if connected to a domain. For each useryou can see the name, domain, SID, etc.
    • Win32_Volume capacity, the free size, the file system, etc.

    This list already provides a wealth of information about a machine. Thereare many more classes available and you can use the "WMI Power Browser" todiscover them and each class instance.

     

    Summary

    WMI provides a powerful way to instrument your application and toallow management tools like Microsoft Operations Manager 2005 to tie intoyour application and proactively notify IT operators. But WMI also providesa wealth of information about systems which you can leverage in yourenterprise applications. It is also very easy to collect that informationfor remote machines or to invoke actions on class instances remotely. The.NET framework provides a comprehensiv
    e and easy approach to working withWMI. It makes it very easy to create WMI classes, expose dynamic WMI classinstances, raise WMI events as well as discover and interact with existingWMI classes and class instances.

    Hopefully future versions of the .NET framework will remove the existinglimitations, the biggest being that you cannot implement methods, cannotprovide write access to properties and only provide dynamic classes. WMI isstill vastly underutilized in today's enterprise applications. Hopefullythese two articles provide a better insight into how to use WMI and thepowerof WMI. If you have comments on this article, please contact me @ klaus_salchner@hotmail.com. Iwant to hear if you learned something new. Contact me if you have questionsabout this topic or article.

    Download Code.zip

     

    About the author

    Klaus Salchner has worked for 14 years in the industry, nine years in Europeand another five years in North America. As a Senior Enterprise Architectwith solid experience in enterprise software development, Klaus spendsconsiderable time on performance, scalability, availability,maintainability, globalization/localization and security. The projects hehas been involved in are used by more than a million users in 50 countrieson three continents.

    Klaus calls Vancouver, British Columbia his home at the moment. His nextbiggoal is doing the New York marathon in 2005. Klaus is interested in guestspeaking opportunities or as an author for .NET magazines or Web sites. Hecan be contacted at klaus_salchner@hotmail.com or http://www.enterprise-minds.com .

    Enterprise application architecture and design consulting services areavailable. If you want to hear more about it contact me! Involve me in yourprojects and I will make a difference for you. Contact me if you have anidea for an article or research project. Also conact me if you want to co-author an article orjoin future research projects!

  • Most Commented Articles :

    Twitter Digg Delicious Stumbleupon Technorati Facebook Email

    No comments yet... Be the first to leave a reply!