The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.


Win32::PerfMon - Perl extension for Windows Perf Monitor (NT4 +)


  use Win32::PerfMon;
  use strict;
  my $ret = undef;
  my $err = undef;
  my $xxx = Win32::PerfMon->new("\\\\MyServer");
  if($xxx != undef)
        $ret = $xxx->AddCounter("System", "System Up Time", -1);
        if($ret != 0)
                $ret = $xxx->CollectData();
                if($ret  != 0)
                        my $secs = $xxx->GetCounterValue("System", "System Up Time", -1);
                        if($secs > -1)
                                print "Seconds of Up Time = [$secs]\n";
                                $err = $xxx->GetErrorText();
                                print "Failed to get the counter data ", $err, "\n";
                        $err = $xxx->GetErrorText();
                        print "Failed to collect the perf data ", $err, "\n";
                $err = $xxx->GetErrorText();
                print "Failed to add the counter ", $err, "\n";
        print "Failed to greate the perf object\n";


This modules provides and interface into the Windows Performance Monitor, which can be found on any Windows Server from NT 4 onwards. The module allows the programmer to add miltiple counters to a query object, and then in a loop, gather the data for those counters. This mechanism is very similar to the native windows method.



All functions return 0 (zero) unless stated otherwise.


This is the constructor for the PerfMon perl object. Calling this function will create a perl object, as well as calling the underlying WIN32 API code to attach the object to the windows Performance Monitor. The function takes as a parameter, the name of the server you wish to get performance counter on. Remember to include the leading slashes.

        my $PerfObj = Win32::PerfMon->new("\\\\SERVERNAME");
AddCounter($ObjectName, $CounterName, $InstanceName)

This function adds the requested counter to the query obejct.

        $PerfObj->AddCounter("Processor", "% Processor Time", "_Total");

Not all counters will have a Instance. This this case, you would simply substitue the Instance with a -1.

If you require performance data onmultiple counter, simply call AddCounter() multiple time, prior to calling collect data

        # Create the object
        my $PerfObj = Win32::PerfMon->new("\\\\SERVERNAME");

        # Add All the counters
        $PerfObj->AddCounter("System", "System Up Time", -1);
        $PerfObj->AddCounter("System","Context Switches/sec", "-1");
        $PerfObj->AddCounter("System","Processes", "-1");
        $PerfObj->AddCounter("Processor","Interrupts/sec", "_Total");
        # Populate the counters from perfmon
        # Now retrieve the data
        my $value = $PerfObj->GetCounterValue("System", "System Up Time", -1);
        etc ....

This function when called, will populate the internal structures with the performance data values. This function should be called after the counters have been added, and before retrieving the counter values.

GetCounterValue($ObjectName, $CounterName, $InstanceName);

This function returns a scaler containing the numeric value for the requested counter. Befoer calling this function, you should call CollectData() to populate the internal structures with the relevent data.

        $PerfObj->GetCounterValue("System", "System Up Time", -1);

Note that if the counter in question does not have a Instance, you should pass in -1; You should call this function for every counter you have added, in between calls to CollectData();

GetCounterValue() can be called in a loop and in conjunction with CollectData() if you wish to gather a series of data, over a period of time.

        # Get the initial values
                # Store the value in question
                my $value = $PerfObj->GetCounterValue("Web", "Current Connections", "_Total");
                # Do something with $value - e.g. store it in a DB
                # Now update the counter value, so that the next call to GetCounterValue has
                # the updated values

Returns the error message from the last failed function call.

        my $err = $PerfObj->GetErrorText();

Lists all the available performance object on the connected machiene. NOTE: This function returns a reference to an array containing the data. The returned list contains the top level Objetcs.

        my $Data = $PerfObj->ListObjects();
        foreach $Object (@$Data)
                print "$Object\n";

Lists all the available performance counters for the specified object on the connected machiene. NOTE: This function returns a reference to an array containing the data.

        my $Data = $PerfObj->ListCounters("System");
        foreach $Counter (@$Data)
                print "$Counter\n";

Lists all the available performance counter instances for the specified object on the connected machiene. NOTE: This function returns a reference to an array containing the data.

        my $Data = $PerfObj->ListInstances("System");
        foreach $Instance (@$Data)
                print "$Instance\n";
RemoveCounter($ObjectName, $CounterName, $InstanceName)

Removes the specifed counter from the query object. All other defined counte will remain. As with other functions, the InstanceName should be replaced with -1 if the Instance is not required.

        $PerfObj->RemoveCounter("System", "System Up Time", -1);

Funtion will return 0 if it didn't work. Most likley reason for a failure is that the specified counter had not been defined in the first place.

ExplainCounter($ObjectName, $CounterName, $InstanceName)

Returns a string containing the counter description, as defined on the current Windows system.

        my $CounterText = $PerfObj->ExplainCounter("System", "System Up Time", -1);

NOTE: You MUST have added the counter to your object beofre calling this function. If you don't actually want to use the counter, you can simple call RemoveCounter() once the function returns.


Glen Small <>