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