• No results found

Using Window Management Instrumentation (WMI)

Chapter 4. User Activity

4.2. NT/2000 Process Control

4.2.4. Using Window Management Instrumentation (WMI)

Let's look at one final approach to NT/2000 process control before we switch to another operating system.

This approach might be subtitled "Futureland" because it involves a technology which isn't widely available now, but is right on the horizon. Window Management Instrumentation (WMI) is available in Windows 2000 (and NT4.0SP4+ if explicitly installed).[2] Over time, when Windows 2000 is widely deployed, this has the potential to become an important part of the NT/2000 administration landscape.

[2]The "Download SDK"page linked off of the WMI section at

http://msdn.microsoft.com/developer/sdk lets you download the core WMI libraries needed to run WMI on an NT4.0SP4 (or higher) machine.

Unfortunately WMI is one of those not−for−the−faint−of−heart technologies that gets very complex, very quickly. It is based on an object−oriented model that has the power to represent not only data, but

relationships between objects as well. For instance, it is possible to create an association between a web server and the Redundant Arrays of Independent Disks (RAID) that holds the data for this server, so if the RAID device should fail, a problem for the web server will be reported as well. To deal with this complexity, we're just going to skim the very surface of WMI by providing a small and simple introduction, followed by a few code samples.

If you want to get a deeper look at this technology, I recommend downloading the WMI white papers, LearnWBM tutorial, and WMI SDK from the WMI section found at

http://msdn.microsoft.com/developer/sdk. You should also have a look at the information found provided at the Distributed Management Task Force's web site, http://www.dtmf.org. In the meantime, here is a brief synopsis to get you started.

WMI is the Microsoft implementation and extension of an unfortunately named initiative called the

Web−Based Enterprise Management initiative, or WBEM for short. Though the name conjures up visions of something that requires a browser, it has virtually nothing to do with the World Wide Web. The companies that were part of the Distributed Management Task Force (DMTF) wanted to create something that could make it easier to perform management tasks using browsers. Putting the name aside, it is clearer to say that WBEM defines a data model for management and instrumentation information. It provides specifications for organizing, accessing, and moving this data around. WBEM is also meant to offer a cohesive frontend for accessing data provided by the other management protocols like Simple Network Management Protocol (SNMP) (discussed in Chapter 10, "Security and Network Monitoring") and Common Management Information Protocol (CMIP).

Data in the WBEM world is organized using the Common Information Model (CIM). CIM is the source of the power and complexity in WBEM/WMI. It provides an extensible data model that contains objects and object classes for any physical or logical entity one might want to manage. For instance, there are object classes for entire networks, and objects for a single slot in a specific machine. There are objects for hardware settings and objects for software application settings. On top of this, CIM allows us to define object classes that describe relationships between other objects.

This data model is documented in two parts: the CIM Specification and the CIM Schema. The former

describes the how of CIM (how the data will be specified, its connection to prior management standards, etc.);

the latter provides the what of CIM (the actual objects). This division may remind you of the SNMP SMI and MIB relationship (see Chapter 10, "Security and Network Monitoring").

The Five−Minute RCS Tutorial (Perl for System Administration)

4.2.4. Using Window Management Instrumentation (WMI) 135

In practice, you'll be consulting the CIM Schema more than the CIM Specification once you get the hang of how the data is represented. The schema format (called MOF for Managed Object Format) is fairly easy to read.

The CIM Schema has two layers:

The core model for objects and classes useful in all types of WBEM interaction.

The common model for generic objects that are vendor− and operating−system independent. Within the common model there are currently five specific areas defined: Systems, Devices, Applications, Networks, and Physical.

Built on top of these two layers can be any number of Extension schema that define objects and classes for vendor− and OS−specific information.

A crucial part of WMI that distinguishes it from generic WBEM implementations is the Win32 Schema, an extension schema for Win32−specific information built on the core and common models. WMI also adds to the generic WBEM framework by providing Win32−specific access mechanisms to the CIM data.[3] Using this schema extension and set of data access methods, we can explore how to perform process control using WMI in Perl.

[3]As much as Microsoft would like to see these data access mechanisms become ubiquitous, the likelihood of finding them in a non−Win32 environment is slight. This is why I refer to them as "Win32−specific."

Two of these access methods, Open Database Connectivity (ODBC) and Compnent Object Model/Distributed Component Object Model (COM/DCOM), will receive a more complete treatment in other places in this book. We're going to use the latter for these examples because ODBC only allows us to query information from WMI (albeit in a simple, database−like manner). COM/DCOM allows us to both query management information and interact with it, crucial for the "control" part of process control.

The Perl code that follows does not appear to be particularly complex, so you may wonder about the "gets very complex, very quickly" description. The code below looks simple because:

We're only scratching the surface of WMI. We're not even going to touch subjects like "associations"

(i.e., relationships between objects and object classes).

The management operations we are performing are simple. Process control in this context will consist of querying the running processes and being able to terminate them at will. These operations are easy in WMI using the Win32 Schema extension.

Our samples are hiding the complexity of translating WMI documentation and code samples in VBscript/JScript to Perl code.

Our samples are hiding the opaqueness of the debugging process. When WMI−related Perl code fails, it does so with very little information that would help debug the problem. You may receive error messages, but they never say ERROR: YOUR EXACT PROBLEM IS.... You're more likely to

4.2.4. Using Window Management Instrumentation (WMI) 136

get back wbemErrFailed 0x8004100 or just an empty data structure. To be fair to Perl, most of this opaqueness comes from Perl's role in this process. It is acting as a frontend to a set of fairly complex multilayered operations that don't concern themselves with passing back useful feedback when something fails.

I know this sounds pretty grim, so let me offer some potentially helpful advice before we actually get into the code itself:

Look at all of the Win32::OLE sample code you can lay your hands on. The ActiveState

Win32−Users mailing list archives found at http://www.activestate.com are a good source for this. If you compare this sample code to equivalent VBscript examples, you'll start to understand the

translation idioms necessary. Section 4.5, "ADSI (Active Directory Service Interfaces)" in Chapter 6,

"Directory Services", may also help.

Make friends with the Perl debugger, and use it to try out code snippets as part of this learning process. Another way to test out Perl snippets on Win32 platforms is to combine the TurboPerl program by William P. Smith (found at http://users.erols.com/turboperl/) with the dumpvar.pl or Data::Dumper modules. It has some bugs (I recommend you save your code often), but in general it can make prototyping Perl code easier. Other Integrated Development Environment tools may also offer this functionality.

Keep a copy of the WMI SDK handy. The documentation and the VBscript code examples are very helpful.

Use the WMI object browser in the WMI SDK frequently. It helps you get the lay of the land.

Let's get to the Perl part of this section. Our initial task will be to determine the information we can retrieve about Win32 processes and how we can interact with that information.

First we need to establish a connection to a WMI namespace. A namespace is defined in the WMI SDK as "a unit for grouping classes and instances to control their scope and visibility." In our case we're interested in connecting to the root of the standard cimv2 namespace, which contains all of the data that is interesting to us.

We will also have to set up a connection with the appropriate security privileges and impersonation level. Our program will need to be given the privilege to debug a process and to impersonate us; in other words, run as the user calling the script. After we get this connection, we will retrieve a Win32_Process object (as defined in the Win32 Schema).

There is a hard way and an easy way to create this connection and get the object. We'll look at both in the first example, so you get an idea of what the methods entail. Here's the hard way, with explanation to follow.

use Win32::OLE('in');

$server = ''; # connect to local machine

# get a SWbemLocator object

$lobj = Win32::OLE−>new('WbemScripting.SWbemLocator') or

die "can't create locator object: ".Win32::OLE−>LastError( )."\n";

# set the impersonate level to "impersonate"

$lobj−>{Security_}−>{impersonationlevel} = 3;

The Five−Minute RCS Tutorial (Perl for System Administration)

4.2.4. Using Window Management Instrumentation (WMI) 137

# use it to get a an SWbemServices object

$sobj = $lobj−>ConnectServer($server, 'root\cimv2') or

die "can't create server object: ".Win32::OLE−>LastError( )."\n";

# get the schema object

$procschm = $sobj−>Get('Win32_Process');

The hard way involves:

Getting a locator object, used to find a connection to a server object

Setting the impersonation so our program will run with our privileges

Using this locator object to get a server connection to the cimv2 WMI namespace

Using this connection to retrieve a Win32_Process object

We can do this all in one step using a COM moniker's display name. According to the WMI SDK, "in Common Object Model (COM), a moniker is standard mechanism for encapsulating the location and binding of another COM object. The textual representation of a moniker is called a display name." Here's an easy way to do the same thing as the previous code snippet:

use Win32::OLE('in');

$procschm = Win32::OLE−>GetObject(

'winmgmts:{impersonationLevel=impersonate}!Win32_Process')

or die "can't create server object: ".Win32::OLE−>LastError( )."\n";

Now that we have a Win32_Process object in hand, we can use it to show us the relevant parts of the schema that represents processes under Win32. This includes all of the available Win32_Process

properties and methods we can use. The code to do this is fairly simple; the only magic in the following code is the use of the Win32::OLEin operator. To explain this, we need a quick digression.

Our $procschm object has two special properties, Properties_ and Methods_. Each holds a special child object, known as a collection object in COM parlance. A collection object is just a parent container for other objects; in this case, they are holding the schema's property method description objects. The in operator just returns an array with references to each child object of a container object. Once we have this array, we can iterate through it, returning the Name property of each child object as we go. See the section on Section 4.5, "ADSI (Active Directory Service Interfaces)" in Chapter 6, "Directory Services" for another prominent use of in. Here's what the code looks like:

use Win32::OLE('in');

# connect to namespace, set the impersonate level, and retrieve the

# Win32_process object just by using a display name

$procschm = Win32::OLE−>GetObject(

'winmgmts:{impersonationLevel=impersonate}!Win32_Process') or die "can't create server object: ".Win32::OLE−>LastError( )."\n";

print "−−− Properties −−−\n";

print join("\n",map {$_−>{Name}}(in $procschm−>{Properties_}));

print "\n−−− Methods −−−\n";

print join("\n",map {$_−>{Name}}(in $procschm−>{Methods_}));

4.2.4. Using Window Management Instrumentation (WMI) 138

The output (on an NT4.0 machine) looks like this:

Let's get down to the business at hand. To retrieve a list of running processes, we need to ask for all instances of Win32_Process objects:

use Win32::OLE('in');

# perform all of the initial steps in one swell foop

$sobj = Win32::OLE−>GetObject(

'winmgmts:{impersonationLevel=impersonate}')

or die "can't create server object: ".Win32::OLE−>LastError( )."\n";

foreach $process (in $sobj−>InstancesOf("Win32_Process")){

print $process−>{Name}." is pid #".$process−>{ProcessId},"\n";

}

Our initial display name did not include a path to a specific object (i.e., we left off !Win32_Process). As a result, we receive a server connection object. When we call the InstancesOf( ) method, it returns a collection object that holds all of the instances of that particular object. Our code visits each object in turn and prints its Name and ProcessId property. This yields a list of all the running processes.

If we want to be a little less beneficent when iterating over each process, we could instead use one of the methods we saw listed above:

foreach $process (in $sobj−>InstancesOf("Win32_Process")){

The Five−Minute RCS Tutorial (Perl for System Administration)

4.2.4. Using Window Management Instrumentation (WMI) 139

$process−>Terminate(1);

}

This will terminate every process running. I do not recommend you run this code as is; customize it for your specific needs by making it more selective.

Now you have the knowledge necessary to begin using WMI for process control. WMI has Win32 extensions for many other parts of the operating system, including the registry and event log facility.

This is as far as we're going to delve into process control on WinNT/2000. Let's turn our attention to one last operating system.

4.1. MacOS Process Control