3

I have a Windows program coded in C++. To get the drive's serial number of the computer's drive, I run "wmic path win32_physicalmedia get SerialNumber" in the program with _popen().

However, the computers that run the program may have many drives, and USB drives also appear in the list.

How can I do to know which of the drives has the program I'm running? Thanks!

NaBUru38
  • 99
  • 1
  • 7
  • Possible duplicate of [Get drive letter from filename in Windows](http://stackoverflow.com/questions/7122009/get-drive-letter-from-filename-in-windows) – Gábor Bakos Oct 05 '15 at 14:49
  • @GáborBakos not dupe, OP is searching for physical drive serial number given a path name. To get drive letter from file name is just second step of this job. – Adriano Repetti Oct 05 '15 at 15:13

1 Answers1

2

Assuming you still want to do it with WMI: first of all you need some code to read WMI properties in C++. No need to repeat here, you can find it in Getting CPU ID code from C# to be in C++.

When you have that code you can stat to work with disks. First of all you need to remember how Windows organize disks:

  • Each physical disk (Win32_DiskDrive) is made by partitions (Win32_DiskPartition).
  • Each partition (Win32_DiskPartition) is a logical disk (Win32_LogicalDisk).
  • Mapping between each other is done with Win32_DiskDriveToDiskPartition and Win32_LogicalDiskToPartition.

You already know where you're running then you can do this mapping:

Fetch from Win32_LogicalDisk the one where DeviceID property matches drive you're running on:

DeviceID=C:

Query Win32_LogicalDiskToPartition and pick Antecedent for which Dependent has ID you previously found:

\\REPETTI\root\cimv2:Win32_DiskPartition.DeviceID="Disk #1, Partition #1"  \\REPETTI\root\cimv2:Win32_LogicalDisk.DeviceID="C:"

Now you should query partitions in Win32_DiskPartition to find the one where DeviceID is Disk #1, Partition #1 however also Win32_DiskDriveToDiskPartition uses DeviceID for this mapping then you can directly query Win32_DiskDriveToDiskPartition to match given ID:

\\REPETTI\root\cimv2:Win32_DiskDrive.DeviceID="\\.\PHYSICALDRIVE1"  \\REPETTI\root\cimv2:Win32_DiskPartition.DeviceID="Disk #1, Partition #1"

Now you just need to query Win32_DiskDrive searching for device ID \\.\PHYSICALDRIVE1:

WDC WDxxx ATA Device  \\.\PHYSICALDRIVE1  WDC WDxxx ATA Device

And you can get its serial number (in this case same property is available both in Win32_PhysicalMedia and Win32_DiskDrive otherwise you should search by its Caption).

Without WMI

If you have to do it without WMI then it's little bit more tricky.

  • First of all you need to figure out which physical drive contains your logical drive_ you may follow How to list physical disks?.
  • When you have physical drive name easiest way is CreateFile() to open drive and get information with DeviceIoControl() sending S.M.A.R.T. commands. Don't think it's always so easy: with many drives it'll fail and you need administrative rights. Unfortunately there isn't a single perfect solution then you need to try different approaches. AFAIK best and most exhaustive code to handle this is written by Lynn McGuire for its DiskId32 utility.
Community
  • 1
  • 1
Adriano Repetti
  • 65,416
  • 20
  • 137
  • 208
  • Thanks! I didn't understand the "\\REPETTI\root" lines, but anyway, I used the WMI commands you listed like this:. – NaBUru38 Oct 06 '15 at 16:36
  • It's computer name (Repetti, in my domain). If you run same queries you will get another name – Adriano Repetti Oct 06 '15 at 16:40
  • Thanks! I didn't understand the "\\REPETTI\root" lines, but I used the WMI commands you listed: 1. Call "GetModuleFileNameW()" to get the partition letter (for example 'C'). 2. Call "wmic logicaldisk where (DeviceID="C:") assoc /assocclass:Win32_LogicalDiskToPartition" to get the partition id ("Disk #0, Partition #1"). 3. Call "wmic partition where (DeviceID="Disk #0, Partition #1") assoc /assocclass:Win32_DiskDriveToDiskPartition" to get the physical drive id ("\\\\.\\PHYSICALDRIVE0"). 4. Call "wmic path win32_diskdrive get deviceid, serialnumber" to get the serial numbers, and search by id. – NaBUru38 Oct 06 '15 at 16:42
  • Right, at first sight that's it! – Adriano Repetti Oct 06 '15 at 16:43