Library tutorials & articles

Using WMI From Managed Code

Working with WMI in .NET

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.

Comments

Leave a comment

Sign in or Join us (it's free).

AddThis

Related podcasts

  • Looking into the C# Crystal Ball with Charlie Calvert and Bill Wagner

    One of the most exciting announcements from PDC was the news about C# 4.0 and Visual Studio 2010. With all the excitement and discussion throughout the event about these new developer tools, we reached out to two experts in the fields. Charlie Calvert and Bill Wagner sat down with Keith and Woody...

Events coming up

  • Dec 6

    Developing AJAX Web Applications with Castle Monorail

    London, United Kingdom

    Monorail is the model-view-controller engine of the Castle Project, bringing many of the best ideas of Ruby on Rails to the .NET world. In this talk, David De Florinier and Gojko Adzic show how Monorail makes it easy to develop .NET based AJAX applications, and how to use the Castle Project to build Web 2.0 applications effectively. Come to this session if you are a .NET web developer. Everyone is welcome!