# HG changeset patch # User Simon Howkins # Date 1270027244 -3600 # Node ID 28714977dccbdf1a9f40216e770427955bc19f52 # Parent 223bb18a2f3c86a8c3c5363b4dfaf06097131830 Bug 2274 - Detection of physical drives doesn't work on Vista/Win7 diff -r 223bb18a2f3c -r 28714977dccb common/tools/findPhysicalDrive.pl --- a/common/tools/findPhysicalDrive.pl Tue Mar 30 17:55:25 2010 +0100 +++ b/common/tools/findPhysicalDrive.pl Wed Mar 31 10:20:44 2010 +0100 @@ -20,6 +20,7 @@ use strict; use Getopt::Long; +use Win32::OLE; # Read option arguments my $option; @@ -43,65 +44,35 @@ exit(1); } -# Use Windows command to list physical volumes on the machine -# (No substed drives, or mapped network drives) -my @details = map {chomp;$_} `echo list volume | diskpart`; - -my @drives; -my %space; -my %capacity; -for my $driveLine (@details) -{ - # If this line of output is actually about a healthy HD volume... - if ($driveLine =~ m{^\s+Volume \d+\s+([A-Z]).*?(Partition|RAID-5)\s+(\d+) ([A-Z]+)\s+Healthy} ) - { - my ($letter, $capacityValue, $capacityUnit) = ($1, $3, $4); - - my %multiplier = ( - MB => 1000000, - GB => 1000000000, - TB => 1000000000000, - ); +# Connect to WMI services on this machine (".") +my $wmiServices = Win32::OLE->GetObject( "winmgmts:{impersonationLevel=impersonate,(security)}//." ) or die; +# Get list of all volumes (drive letters) +my @volumes = Win32::OLE::in($wmiServices->InstancesOf( "Win32_LogicalDisk" )); +# Get list of substed drives +my %subst = map { (substr $_, 0, 2) => 1 } `subst`; +# Filter volumes to remove non-Partitions, and substed drives +@volumes = grep { $_->{DriveType} == 3 && !exists $subst{$_->{DeviceID}} } @volumes; +# Also remove the system drive (usually C:) unless it's the only drive in the box! +@volumes = grep { $_->{DeviceID} ne $ENV{SystemDrive} } @volumes if scalar(@volumes) > 1; - if (not exists $multiplier{$capacityUnit}) - { - warn "Don't know how to interpret $capacityValue $capacityUnit\n"; - next; - } - $capacityValue *= $multiplier{$capacityUnit}; - - # Ignore the system drive - next if ($driveLine =~ m{System\s*$}); - - # Use dir to get the freespace (bytes) - my @bytesFree = grep { s{^.*?(\d+) bytes free\s*$}{$1} } map {chomp;$_} `cmd /c dir /-C /A $letter:\\`; - # Take the value from the bottom of the report - my $bytesFree = $bytesFree[-1]; - - # Record info for this volume - push @drives, $letter; - $space{$bytesFree} = $letter; - $capacity{$capacityValue} = $letter; - } -} - -die "Unable to find any suitable drives at all\n" unless %space; +die "Unable to find any suitable drives at all\n" unless @volumes; if ($option->{all}) { - print join ",", map { "$_:" } @drives; + print join ",", map { $_->{DeviceID} } @volumes; print "\n"; - exit; } elsif ($option->{capacity}) { # Sort by capacity to find the largest volume and print out the corresponding letter - print "$capacity{(reverse sort keys %capacity)[0]}:\n"; + @volumes = reverse sort { $a->{Size} <=> $b->{Size} } @volumes; + print "$volumes[0]->{DeviceID}\n"; } elsif ($option->{space}) { # Sort by space to find the volume with the largest amount of space and print out the corresponding letter - print "$space{(reverse sort keys %space)[0]}:\n"; + @volumes = reverse sort { $a->{FreeSpace} <=> $b->{FreeSpace} } @volumes; + print "$volumes[0]->{DeviceID}\n"; } exit;