common/tools/findPhysicalDrive.pl
changeset 955 28714977dccb
parent 924 a5ed0e6ca679
equal deleted inserted replaced
954:223bb18a2f3c 955:28714977dccb
    18 #  * The list of all such drives
    18 #  * The list of all such drives
    19 
    19 
    20 use strict;
    20 use strict;
    21 
    21 
    22 use Getopt::Long;
    22 use Getopt::Long;
       
    23 use Win32::OLE;
    23 
    24 
    24 # Read option arguments
    25 # Read option arguments
    25 my $option;
    26 my $option;
    26 my $ok = GetOptions(
    27 my $ok = GetOptions(
    27 	'capacity' => \$option->{capacity},
    28 	'capacity' => \$option->{capacity},
    41 	warn "Exactly one option must be supplied to indicate the required output\n$ok\n@ARGV\n";
    42 	warn "Exactly one option must be supplied to indicate the required output\n$ok\n@ARGV\n";
    42 	usage();
    43 	usage();
    43 	exit(1);
    44 	exit(1);
    44 }
    45 }
    45 
    46 
    46 # Use Windows command to list physical volumes on the machine
    47 # Connect to WMI services on this machine (".")
    47 # (No substed drives, or mapped network drives)
    48 my $wmiServices = Win32::OLE->GetObject( "winmgmts:{impersonationLevel=impersonate,(security)}//." ) or die;
    48 my @details = map {chomp;$_} `echo list volume | diskpart`;
    49 # Get list of all volumes (drive letters)
       
    50 my @volumes = Win32::OLE::in($wmiServices->InstancesOf( "Win32_LogicalDisk" ));
       
    51 # Get list of substed drives
       
    52 my %subst = map { (substr $_, 0, 2) => 1 } `subst`;
       
    53 # Filter volumes to remove non-Partitions, and substed drives
       
    54 @volumes = grep { $_->{DriveType} == 3 && !exists $subst{$_->{DeviceID}} } @volumes;
       
    55 # Also remove the system drive (usually C:) unless it's the only drive in the box!
       
    56 @volumes = grep { $_->{DeviceID} ne $ENV{SystemDrive} } @volumes if scalar(@volumes) > 1;
    49 
    57 
    50 my @drives;
    58 die "Unable to find any suitable drives at all\n" unless @volumes;
    51 my %space;
       
    52 my %capacity;
       
    53 for my $driveLine (@details)
       
    54 {
       
    55 	# If this line of output is actually about a healthy HD volume...
       
    56 	if ($driveLine =~ m{^\s+Volume \d+\s+([A-Z]).*?(Partition|RAID-5)\s+(\d+) ([A-Z]+)\s+Healthy} )
       
    57 	{
       
    58 		my ($letter, $capacityValue, $capacityUnit) = ($1, $3, $4);
       
    59 		
       
    60 		my %multiplier = (
       
    61 			MB => 1000000,
       
    62 			GB => 1000000000,
       
    63 			TB => 1000000000000,
       
    64 		);
       
    65 
       
    66 		if (not exists $multiplier{$capacityUnit})
       
    67 		{
       
    68 			warn "Don't know how to interpret $capacityValue $capacityUnit\n";
       
    69 			next;
       
    70 		}
       
    71 		$capacityValue *= $multiplier{$capacityUnit};
       
    72 
       
    73 		# Ignore the system drive
       
    74 		next if ($driveLine =~ m{System\s*$});
       
    75 
       
    76 		# Use dir to get the freespace (bytes)
       
    77 		my @bytesFree = grep { s{^.*?(\d+) bytes free\s*$}{$1} } map {chomp;$_} `cmd /c dir /-C /A $letter:\\`;
       
    78 		# Take the value from the bottom of the report
       
    79 		my $bytesFree = $bytesFree[-1];
       
    80 
       
    81 		# Record info for this volume
       
    82 		push @drives, $letter;
       
    83 		$space{$bytesFree} = $letter;
       
    84 		$capacity{$capacityValue} = $letter;
       
    85 	}
       
    86 }
       
    87 
       
    88 die "Unable to find any suitable drives at all\n" unless %space;
       
    89 
    59 
    90 if ($option->{all})
    60 if ($option->{all})
    91 {
    61 {
    92 	print join ",", map { "$_:" } @drives;
    62 	print join ",", map { $_->{DeviceID} } @volumes;
    93 	print "\n";
    63 	print "\n";
    94 	exit;
       
    95 }
    64 }
    96 elsif ($option->{capacity})
    65 elsif ($option->{capacity})
    97 {
    66 {
    98 	# Sort by capacity to find the largest volume and print out the corresponding letter
    67 	# Sort by capacity to find the largest volume and print out the corresponding letter
    99 	print "$capacity{(reverse sort keys %capacity)[0]}:\n";
    68 	@volumes = reverse sort { $a->{Size} <=> $b->{Size} } @volumes;
       
    69 	print "$volumes[0]->{DeviceID}\n";
   100 }
    70 }
   101 elsif ($option->{space})
    71 elsif ($option->{space})
   102 {
    72 {
   103 	# Sort by space to find the volume with the largest amount of space and print out the corresponding letter
    73 	# Sort by space to find the volume with the largest amount of space and print out the corresponding letter
   104 	print "$space{(reverse sort keys %space)[0]}:\n";
    74 	@volumes = reverse sort { $a->{FreeSpace} <=> $b->{FreeSpace} } @volumes;
       
    75 	print "$volumes[0]->{DeviceID}\n";
   105 }
    76 }
   106 
    77 
   107 exit;
    78 exit;
   108 
    79 
   109 sub usage
    80 sub usage