Hey all, I've been hacking away at this for a few hours. Getting an OLE VT_DISPATCH object back as an out parameter is a lot trickier than I thought it would be. Hope it helps so that it doesn't take you as long! :-)
This has been tested and works like a charm in ActiveState Perl 5.8.8.
use Win32::OLE('in');
use Win32::OLE::Variant;
use constant wbemFlagReturnImmediately => 0x10;
use constant wbemFlagForwardOnly => 0x20;
%return_code = (
0 => 'Success',
1 => 'Access denied',
2 => 'Not supported',
3 => 'Volume dirty bit is set',
4 => 'Not enough free space',
5 => 'Corrupt master file table detected',
6 => 'Call canceled',
7 => 'Call cancellation request too late',
8 => 'Defrag engine is already running',
9 => 'Unable to connect to defrag engine',
10 => 'Defrag engine error',
11 => 'Unknown error',
);
$host = ".";
$objWMI = Win32::OLE->GetObject
("winmgmts:{impersonationLevel=impersonate}!\\\\$host\\root\\cimv2")
or die "WMI connection failed.\n";
$colItems = $objWMI->ExecQuery("Select * from Win32_Volume where " .
"DriveType = 3", "WQL", wbemFlagReturnImmediately | wbemFlagForwardOnly)
or die "Unable to query.\n";
foreach $objItem (in $colItems)
{
$df_recommended = Variant(VT_BOOL|VT_BYREF, 0);
$df_a = Variant(VT_DISPATCH|VT_BYREF);
$result = $objItem->DefragAnalysis($df_recommended, $df_a);
$df_a = $df_a->Value();
if ($result == 0) { # Success
print "Volume $objItem->{Name}\n";
print " Defrag recommended: ".($df_recommended ? "Yes" : "No") ."\n";
print " Average file size: ".$df_a->{AverageFileSize} ."\n";
print " Total files: ".$df_a->{TotalFiles} ."\n";
print " File fragmentation: ".$df_a->{FilePercentFragmentation} ."\n";
print " Used space: ".$df_a->{UsedSpace} ."\n";
print " Free space: ".$df_a->{FreeSpace} ."\n";
print " MFT percent in use: ".$df_a->{MFTPercentInUse} ."\n";
# ...and whatever other properties you want to see
print "\n";
}
else {
print "Volume $objItem->{Name}\n";
print " " . $return_code{$result} . "\n";
print "\n";
}
}