Using WMI From Managed Code

Page 2 of 3
  1. Introduction
  2. Working with WMI in .NET
  3. Running Methods

Working with WMI in .NET

This article was originally published on DNJ Online
DNJ Online
This article was originally published on DNJ Online
DNJ

Programs written in a .NET language can access WMI through the COM Inter-op technology. To demonstrate this we’ll look at a C# application that uses the WMI Win32_Printer class to create a new managed object and put it in the repository; get an existing object and modify its properties; run a method of a particular class; and delete an object from the repository.

WMI is exposed to .NET through the System.Management library. In order to use it we need to add a reference to System.Management.dll. We then start by creating the class WMIHelper:

class WMIHelper {
  private ManagementScope managementScope = null;
  ...
}

Before we can start any WMI activity we need to create a connection to the WMI repository either on the local or a remote machine. If we are connecting to a local machine we create a default ConnectionOptions class instance. If we’re going for a remote machine we set the username and password to specify a user who has rights to access WMI functionality (typically a member of Administrators group). Once this is done the ManagementScope can be created using the WMI path and ConnectionOptions. The Win32_Printer class, as with all WMI Win32 classes, is located under root\cimv2 on the local or remote machine:

public WMIHelper( string serverName, string adminUser, 
    		string adminUserPassword) 
{ 
    try 
    { 
    	ConnectionOptions connectionOptions = 
    			   new ConnectionOptions(); 
    	string wmiPath; 
    	if(serverName == null || serverName.Length == 0 || 
    	   adminUser == null || adminUser.Length == 0 || 
    			adminUserPassword == null || 
    			adminUserPassword.Length == 0) 
    		{ 
    		   //specify WMI path for local machine 
    		   wmiPath = @"root\cimv2";  
    		}  
    		else 
    		{  
    			//set connection parameters for remote machine  
    			connectionOptions.Username = adminUser;  
    			connectionOptions.Password = adminUserPassword;  
    			//specify WMI path for remote machine 
    			wmiPath = String.Format(
    					@"\\{0}\root\cimv2", serverName);  
    		}  
    	managementScope = new ManagementScope(wmiPath, connectionOptions); 
    }  
    	catch( Exception ex) 
    { 
    	throw new Exception( 
    	  String.Format( "WMI exception: {0}", ex.Message));  
    }
}

From this point on the code will work with both local and remote modes.

Creating a new object

So let’s create a new printer object and put it into the repository. The relevant properties for the Win32_Printer class are as follows:

class Win32_Printer : CIM_Printer  {  
     string DeviceID;  
     string DriverName;  
     string PortName;  
     boolean Shared;  
     string ShareName; 
}; 

First we create the helper method InitClass which takes the WMI class name (Win32_Printer in our case) and, using the management scope initialised in the constructor, returns a ManagementClass:

private ManagementClass InitClass( string className)  {  
   //specify Printer class management path  
   ManagementPath managementPath = 
    			 new ManagementPath(className);  
   try  
   {  
      //create new WMI management class  
      return new ManagementClass(

    			 managementScope, managementPath, null);  
   }  
   catch ( Exception ex)  
   { 
      throw new Exception( 
         String.Format( 
        "WMI exception: {0}", ex.Message));  
   }
}

Here’s the code which adds a new printer object to the repository based on its name, the name of the printer driver and the port, and whether we want it to be shared or not. The function returns true if the printer is successfully added, or false if there is a problem:

public bool AddPrinter( 
               string printerName, string printerDriver,  
               string portName, bool sharedPrinter)  
{  
    bool result = false;  
    try  
    { 
      //init Win32_Printer class 
        ManagementClass printerClass = 
                        InitClass( "Win32_Printer"); 
      //create new Win32_Printer object 
        ManagementObject printerObject = 
                   printerClass.CreateInstance(); 
      //set port parameters 
    	if (portName == null || portName.Length == 0) 
    	    printerObject[ "PortName"] = "LPT1:"; 
    	else 
    	{ 
    		if (portName[portName.Length - 1] != ':') 
    			printerObject[ "PortName"] = (portName + ":"); 
    		else 
    			printerObject[ "PortName"] = portName; 
    	}
    	//set driver and device names 
    	printerObject[ "DriverName"] = printerDriver; 

    	printerObject[ "DeviceID"] = printerName; 
    	//set sharing 
    	if (sharedPrinter) 
    	{ 
    		printerObject[ "Shared"] = sharedPrinter; 
    		printerObject[ "ShareName"] = printerName; 
    	} 
    	// specify put options: update or create 
    	PutOptions options = new PutOptions(); 
    	options.Type = PutType.UpdateOrCreate; 
    		//put a newly created object to WMI objects set 
    	printerObject.Put(options); 

    	result = true; 
    } 
    catch ( Exception ex) 
    { 
        throw new Exception(  String.Format( "WMI exception: {0}", ex.Message)); 
    } 
  return result; 
}

We start by creating the appropriate ManagementClass with the help of InitClass, and then create a new instance in printerObject. Next we set the necessary properties for the object, and then we Put the object into the repository. Prior to doing that we set its PutOptions to ‘UpdateOrCreate’, which means ‘save the object whether this involves updating an existing object or creating a new one’. Once this is done a new printer will appear in the system.

Modifying Objects &

You might also like...

Comments

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“It is practically impossible to teach good programming style to students that have had prior exposure to BASIC. As potential programmers, they are mentally mutilated beyond hope of regeneration.” - E. W. Dijkstra