Subscribe to Windows IT Pro

 

Get Newsletters

  • Get the Latest News
  • Product Updates
  • Helpful Tricks
  • Productivity Tips

Subscribe Now!

February 26, 2001 12:00 AM

Progressive Perl for Windows: Using WMI to Request Data About Disk Drives

Windows IT Pro
InstantDoc ID #19828
Rating: (0)
Downloads
19828.zip

Last month, I discussed EventMon.pl, a script that monitors events in logs on remote Win32 machines and displays those events in realtime. The magic behind this script is Windows Management Instrumentation (WMI). In my explanation of EventMon.pl, I mentioned that you ought to become familiar with WMI. This month, I insist on it.

Many of you are probably rolling your eyes right now and moaning about yet another Microsoft technology to learn. WMI is well worth learning because it offers a rich set of features that will meet most of your administrative needs. With WMI, your Perl scripts can query a machine's settings, processes, hardware, and more. These scripts can even monitor events that a remote machine fires.

To help you learn WMI, I explain how to access WMI from Perl. In addition, I provide a practical example of how you can use WMI with Perl. I don't focus on the nitty-gritty but rather give a cursory overview of the information you need to start using this technology.

Understanding WMI
WMI is Microsoft's version of an industrywide initiative called Web-Based Enterprise Management (WBEM). This initiative uses the Common Information Model (CIM), which describes how information is obtained.

Classes are key to WMI. Think of a class as a blueprint. Architects create blueprints to inform others about a building's design and characteristics. For example, a house's blueprint tells you the size of the rooms, the number of fireplaces, and other pertinent information. Builders use that blueprint to create a physical manifestation of the house.

Similarly, code writers create classes to inform others about objects' properties and functions (also called methods). In the case of WMI, Microsoft code writers created WMI classes to describe objects that represent computer components. For example, the Win32_DiskDrive class describes the object that represents a machine's physical disk drive. This class tells you the size of the disk drive, the number of heads, and other pertinent data. Perl scripts use that class to create a physical manifestation, or instance, of the object in the computer's memory. You can then examine and explore the object, just as you might examine and explore a new house. WMI classes exist for all types of information. Classes address a computer's physical characteristics (e.g., memory), OS (e.g., available virtual memory), applications (e.g., installed programs), subsystems (COM components), and more.

Using WMI Classes
To request that a machine create an instance of, or instantiate, a class into an object, you need to know which class to request. You can access WMI Win32 class information from the Microsoft Developer Network (MSDN) Online Library. After you know which class you want to use, you can instantiate that class by following these steps:

  1. Load the Win32::OLE extension.

  2. Request an instance of the object that represents the WMI service on the target machine.

  3. Request all instances of the target class.

  4. Enumerate each instance in the target class.

For example, let's use WMI to request information about a machine's disk drives, which means you need to instantiate the Win32_DiskDrive class.

Step 1
The first step is to load the Win32::OLE extension. This extension's name is misleading because Win32::OLE doesn't have much to do with OLE; instead, the extension has more to do with COM.

The Win32::OLE extension comes with ActivePerl, so you probably already have the extension installed. (If you don't have ActivePerl, you can download it from ActiveState Tool at http://www.activestate.com.) If you're unfamiliar with the Win32::OLE extension, I recommend you learn about it because it's one of the most useful Win32 extensions.

To load the extension, you use the code that Listing 1 shows for Step 1. In addition to loading the extension, this code imports the in() function so that you can use it later in your script (more on this function later).

Related Content:

ARTICLE TOOLS

Comments
  • Anonymous User
    7 years ago
    Feb 20, 2005

    no comment

  • Rahul Bhiide
    8 years ago
    Jun 24, 2004

    We can find the drives on a machine using Win32_LogicalDisk and can find target lun bus numbers using Win32_DiskDrive . but how to find the mapping between the drive letters and targets/lun/bus .

  • Dave Roth
    10 years ago
    Aug 23, 2002

    You can use the ExecQuery() method off of the WMI Services script object to solve this. The query is very similar to SQL and would allow you to specify that you want all Win32_LogicalDisk instances where the DeviceID is greater than or equal to "C:". You could make more sophisticated queries such as collect all instances between drives D: and L:, if you like. Try this Perl code:




    use strict;

    use Win32::OLE qw( in );

    $Machine = ".";

    my $WMIServices = Win32::OLE->GetObject

    ( "winmgmts:{impersonationLevel=impersonate,

    (security)}//$Machine/root/cimv2" ) || die;

    my $DriveCollection = $WMIServices->ExecQuery

    ( 'select * from Win32_LogicalDisk where

    DeviceID >= "C:"' ) || die "Query Failed";

    foreach my $Drive ( in( $DriveCollection ) )

    {

    my $FreePercent = int( ( $Drive->{FreeSpace} / $Drive->{Size} ) * 100 );

    print "$Drive->{DeviceID}\\n";

    print "\\tVolume: $Drive->{VolumeName}\\n";

    print "\\tDisk Size: " . FormatNumber( $Drive->{Size} ) . "\\n";

    print "\\tAvailable: " . FormatNumber( $Drive->{FreeSpace} ) . "

    ($FreePercent%)\\n";

    print "\\n";

    }



    sub FormatNumber

    {

    my($Number) = @_;

    my $Suffix = "";

    if( $Number > 1024 * 1024 * 1024 )

    {

    $Number /= (1024 * 1024 * 1024);

    $Suffix = "G";

    }

    elsif( $Number > 1024 * 1024 )

    {

    $Number /= (1024 * 1024);

    $Suffix = "M";

    }

    elsif( $Number > 1024 )

    {

    $Number /= 1024;

    $Suffix = "K";

    }

    $Number = sprintf( "%0.2f", $Number );

    while( $Number =~ s/^(-?\\d+)(\\d{3})/$1,$2/ ){};

    return( $Number . $Suffix );

    }



  • Sanjeev Shukla
    10 years ago
    Jun 17, 2002

    I am using WMI with Perl, but whenever I access the logical disks using Logical_disk class, the script scans the floppy drives as well. I am trying to find a way so that I can get data only about logical disk without scanning floppy drives every time script runs (as this may damage floppy drives on the server, if I run the script very frequently).

You must log on before posting a comment.

Are you a new visitor? Register Here

advertisement

advertisement

White Papers

Get your Windows 7 deployment off to the right start by implementing PC lockdown. A locked-down environment is easier and cheaper to support since users are less likely to make unnecessary changes to the core system configuration - read more here!

Essential Guides

Is your iSCSI "lossy"? The reality is that most off-the-shelf Ethernet hardware deployed for iSCSI can lose packets, resulting in slow performance or application downtime. Learn how to assess your current iSCSI infrastructure and engineer an advanced iSCSI SAN infrastructure.

Web Seminars

What's the best way to keep your network safe from malware? In this web seminar, security expert Greg Shields suggests an alternative method to the traditional blacklisting approach that is common with anti-virus and anti-malware solutions.

eLearning Series

We bring the experts direct to you to share their real-world perspective and expertise. During each event, three sessions stream in real time, so you can learn, ask questions, and get solutions.
Upcoming event: Getting the Most with Exchange 2010 with Paul Robichaux

Subscribe to Windows IT Pro!

Windows is a trademark of the Microsoft group of companies. Windows IT Pro is used by Penton Media Inc. under license from owner.