C# - WMI 논리 디스크가 속한 물리 디스크의 정보를 얻는 방법
다음과 같은 질문이 있군요. ^^
드라이브 문자를 통해서 물리 디스크 명칭을 알아내고 싶습니다.
; https://www.sysnet.pe.kr/3/0/5803
윈도우에서 "drive"는 논리적인 디스크 정보에 해당합니다. 즉, "물리적인 하드 디스크"를 1개 구매해서, 거기에 3개의 파티션을 나눈 다음 각각 C, D, E 드라이브 문자를 할당할 수 있는데요, 그런 경우 다음과 같이 정리할 수 있습니다.
물리 디스크 0
논리 디스크 0 - C
논리 디스크 1 - D
논리 디스크 2 - E
그러니까, 논리 디스크 자체에는
물리 디스크의 Serial number를 확인할 수 없습니다. 그것을 확인하기 위해서는 논리 디스크가 속한 물리 디스크를 먼저 구하는 선행 작업이 필요합니다.
결국 문제는, 논리 디스크(
Win32_LogicalDisk)와 물리 디스크의 관계를 연결할 수 있는 접점이 필요한 건데요, 이에 대해서는 다음의 Q&A에서 잘 설명하고 있습니다.
WMI Association of LogicalDisk with DiskPartition
; https://stackoverflow.com/questions/48116174/wmi-association-of-logicaldisk-with-diskpartition
위의 글에서 설명하듯이, 논리 디스크 정보에 포함된 "VolumeSerialNumber" 고윳값이
Win32_DiskDriveToDiskPartition을 통해 물리 디스크 정보인
Win32_DiskDrive에 대한 교각 역할을 합니다.
따라서 다음과 같이 코딩을 하면,
using System.Management;
using System.Runtime.Versioning;
using ConsoleApp1;
[assembly: SupportedOSPlatform("windows")]
// Install-Package System.Management
internal class Program
{
static void Main(string[] args)
{
List<Win32_DiskDrive> physicalDisks = GetPhysicalDiskList();
foreach (Win32_LogicalDisk drive in GetLogicalDiskList())
{
Console.WriteLine($"{nameof(drive.DeviceID)}: {drive.DeviceID}");
Console.WriteLine($"{nameof(drive.VolumeSerialNumber)}: {drive.VolumeSerialNumber}");
drive.PhysicalDisk = physicalDisks.Find(disk => disk.Partitions.Find(partition => partition.VolumeSerialNumber == drive.VolumeSerialNumber) != null);
if (drive.PhysicalDisk != null)
{
Console.WriteLine($"{nameof(drive.PhysicalDisk.SerialNumber)}: {drive.PhysicalDisk.SerialNumber}");
Console.WriteLine($"{nameof(drive.PhysicalDisk.DeviceID)}: {drive.PhysicalDisk.DeviceID}");
}
Console.WriteLine();
}
}
public static List<Win32_LogicalDisk> GetLogicalDiskList()
{
List<Win32_LogicalDisk> drives = new List<Win32_LogicalDisk>();
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_LogicalDisk");
foreach (ManagementObject queryObj in searcher.Get())
{
Win32_LogicalDisk item = new Win32_LogicalDisk();
item.Caption = queryObj.GetAsString("Caption");
item.Description = queryObj.GetAsString("Description");
item.DeviceID = queryObj.GetAsString("DeviceID");
item.Name = queryObj.GetAsString("Name");
item.VolumeName = queryObj.GetAsString("VolumeName");
item.VolumeSerialNumber = queryObj.GetAsString("VolumeSerialNumber");
drives.Add(item);
}
}
catch (ManagementException)
{
}
return drives;
}
public static List<Win32_DiskDrive> GetPhysicalDiskList()
{
List<Win32_DiskDrive> drives = new List<Win32_DiskDrive>();
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_DiskDrive");
foreach (ManagementObject queryObj in searcher.Get())
{
Win32_DiskDrive item = new Win32_DiskDrive();
item.DeviceID = queryObj.GetAsString("DeviceID");
item.Caption = queryObj.GetAsString("Caption");
item.Description = queryObj.GetAsString("Description");
item.Index = queryObj.GetAsUInt32("Index");
item.SerialNumber = queryObj.GetAsString("SerialNumber").Trim();
item.PNPDeviceID = queryObj.GetAsString("PNPDeviceID");
ListPartitions(item);
drives.Add(item);
}
}
catch (ManagementException)
{
}
return drives;
}
// https://stackoverflow.com/questions/48116174/wmi-association-of-logicaldisk-with-diskpartition
private static void ListPartitions(Win32_DiskDrive drive)
{
string assocQuery = $"Associators of {{Win32_DiskDrive.DeviceID='{drive.DeviceID}'}} where AssocClass=Win32_DiskDriveToDiskPartition";
var assocPart = new ManagementObjectSearcher(assocQuery);
assocPart.Options.Timeout = System.Management.EnumerationOptions.InfiniteTimeout;
foreach (ManagementObject moPart in assocPart.Get())
{
string logDiskQuery = $"Associators of {{Win32_DiskPartition.DeviceID='{moPart.Properties["DeviceID"].Value.ToString()}'}} where AssocClass=Win32_LogicalDiskToPartition";
var logDisk = new ManagementObjectSearcher(logDiskQuery);
logDisk.Options.Timeout = System.Management.EnumerationOptions.InfiniteTimeout;
foreach (var logDiskEnu in logDisk.Get())
{
Win32_DiskDriveToDiskPartition partition = new Win32_DiskDriveToDiskPartition();
partition.VolumeSerialNumber = logDiskEnu.GetAsString("VolumeSerialNumber");
drive.Partitions.Add(partition);
}
}
}
}
public class Win32_LogicalDisk
{
public string Caption = "";
public string Description = "";
public string DeviceID = "";
public string Name = "";
public string VolumeName = "";
public string VolumeSerialNumber = "";
public Win32_DiskDrive? PhysicalDisk;
}
public class Win32_DiskDrive
{
public string DeviceID = "";
public string Caption = "";
public string Description = "";
public uint Index;
public string SerialNumber = "";
public string PNPDeviceID = "";
public List<Win32_DiskDriveToDiskPartition> Partitions = new List<Win32_DiskDriveToDiskPartition>();
}
public class Win32_DiskDriveToDiskPartition
{
public string VolumeSerialNumber = "";
}
실행 시 이와 같은 결과가 나옵니다.
Ligical-DeviceID: C:
VolumeSerialNumber: C54B0E7F
SerialNumber: 0015_4222_153C_557E.
Physical-DeviceID: \\.\PHYSICALDRIVE1
Ligical-DeviceID: D:
VolumeSerialNumber: D29D0282
SerialNumber: 0015_4222_153C_5562.
Physical-DeviceID: \\.\PHYSICALDRIVE2
Ligical-DeviceID: E:
VolumeSerialNumber: A8A69CBD
SerialNumber: 0015_4222_153C_5562.
Physical-DeviceID: \\.\PHYSICALDRIVE2
Ligical-DeviceID: F:
VolumeSerialNumber: 38C805A0
SerialNumber: WD-WXT1DC0JKWHY
Physical-DeviceID: \\.\PHYSICALDRIVE0
실제로 해당 시스템에 설치된 물리 디스크에 따른 디스크 정보는 아래와 같은 상황입니다.
물리 디스크 - PHYSICALDRIVE0
논리 디스크 F:
물리 디스크 - PHYSICALDRIVE1
논리 디스크 C:
물리 디스크 - PHYSICALDRIVE2
논리 디스크 D:
논리 디스크 E:
(
첨부 파일은 이 글의 예제 코드를 포함합니다.)
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]