use strict; use warnings; use Win32::OLE qw(in); my $Machine = shift @ARGV || "."; $Machine =~ s/^[\\\/]+//; my $WMIServices = Win32::OLE->GetObject( "winmgmts:{impersonationLevel=impersonate,(security)}//$Machine") || die "Could not get Win32::OLE Object.\n"; my %serial; # Serial Number hash based on device name my %device; # Drive Letter Based on Device Name # Populate Serial Hash my $PhysMediaCollection = $WMIServices->InstancesOf( "Win32_PhysicalMedia" ); foreach my $PM (in ($PhysMediaCollection)) { my $name = (split(/=/, $PM->{Path_}->relpath))[1]; $serial{eval $name}=$PM->{SerialNumber}; } # Loop Over Hard Disks my $DiskDriveCollection = $WMIServices->InstancesOf( "Win32_DiskDrive" ); #my $DiskDriveCollection = $WMIServices->ExecQuery("SELECT Caption, DeviceID FROM Win32_DiskDrive"); foreach my $DiskDrive (in($DiskDriveCollection)) { my $cap_disk = $DiskDrive->{Caption}; my $did_disk = $DiskDrive->{DeviceID}; my $query_did = $did_disk; $query_did =~ s/\\/\\\\/sg; # Very important to change slashy formatting my $query = 'ASSOCIATORS OF ' . '{Win32_DiskDrive.DeviceID="' . $query_did . '"} WHERE AssocClass = Win32_DiskDriveToDiskPartition'; my $DiskPartCollection = $WMIServices->ExecQuery($query); #Loop Over Partitions foreach my $Partition (in($DiskPartCollection)) { my $did_part = $Partition->{DeviceID}; my $query = 'ASSOCIATORS OF {Win32_DiskPartition.DeviceID=\'' . $did_part . "\'} WHERE AssocClass = Win32_LogicalDiskToPartition"; my $LogDriveCollection = $WMIServices->ExecQuery($query); # Loop Over Logical Drives foreach my $LogDrive (in($LogDriveCollection)) { my $did_log = $LogDrive->{DeviceID}; $device{$did_log} = $did_disk; } # Next Logical Drive } # Next Partition } # Next Hard Disk # Print Results foreach my $letter (keys %device) { my $sn = $serial{$device{$letter}}; print "Drive $letter maps to drive with S/N $sn \n"; }