Reputation: 995
I need to check in C# if a hard disk is SSD (Solid-state drive), no seek penalty? I used:
ManagementClass driveClass = new ManagementClass("Win32_DiskDrive");
ManagementObjectCollection drives = driveClass.GetInstances();
But its only gives Strings that contain SSD in the properties, I can't depend on that?
I Need a direct way to check that?
Upvotes: 18
Views: 13644
Reputation: 205
This is how to check drive type by string path.
public enum DriveType
{
None = 0,
Hdd,
Ssd
}
public static DriveType GetDriveType(string path)
{
try
{
var rootPath = Path.GetPathRoot(path);
if (string.IsNullOrEmpty(rootPath))
{
return DriveType.None;
}
rootPath = rootPath[0].ToString();
var scope = new ManagementScope(@"\\.\root\microsoft\windows\storage");
scope.Connect();
using var partitionSearcher = new ManagementObjectSearcher($"select * from MSFT_Partition where DriveLetter='{rootPath}'");
partitionSearcher.Scope = scope;
var partitions = partitionSearcher.Get();
if (partitions.Count == 0)
{
return DriveType.None;
}
string? diskNumber = null;
foreach (var currentPartition in partitions)
{
diskNumber = currentPartition["DiskNumber"].ToString();
if (!string.IsNullOrEmpty(diskNumber))
{
break;
}
}
if (string.IsNullOrEmpty(diskNumber))
{
return DriveType.None;
}
using var diskSearcher = new ManagementObjectSearcher($"SELECT * FROM MSFT_PhysicalDisk WHERE DeviceId='{diskNumber}'");
diskSearcher.Scope = scope;
var physicakDisks = diskSearcher.Get();
if (physicakDisks.Count == 0)
{
return DriveType.None;
}
foreach (var currentDisk in physicakDisks)
{
var mediaType = Convert.ToInt16(currentDisk["MediaType"]);
switch (mediaType)
{
case 3:
return DriveType.Hdd;
case 4:
return DriveType.Ssd;
default:
return DriveType.None;
}
}
return DriveType.None;
}
catch (Exception ex)
{
// TODO: Log error.
return DriveType.None;
}
}
Upvotes: 1
Reputation: 133
This will give you the result on Win10
ManagementScope scope = new ManagementScope(@"\\.\root\microsoft\windows\storage");
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM MSFT_PhysicalDisk");
string type = "";
scope.Connect();
searcher.Scope = scope;
foreach (ManagementObject queryObj in searcher.Get())
{
switch (Convert.ToInt16(queryObj["MediaType"]))
{
case 1:
type = "Unspecified";
break;
case 3:
type = "HDD";
break;
case 4:
type = "SSD";
break;
case 5:
type = "SCM";
break;
default:
type = "Unspecified";
break;
}
}
searcher.Dispose();
P.s. the string type is the last drive, change to an array to get it for all drives
Upvotes: 10
Reputation: 138925
WMI will not be able to determine this easily. There is a solution here that's based on the same algorithm Windows 7 uses to determine if a disk is SSD (more on the algorithm here: Windows 7 Enhancements for Solid-State Drives, page 8 and also here: Windows 7 Disk Defragmenter User Interface Overview): Tell whether SSD or not in C#
A quote from the MSDN blog:
Disk Defragmenter looks at the result of directly querying the device through the ATA IDENTIFY DEVICE command. Defragmenter issues IOCTL_ATA_PASS_THROUGH request and checks IDENTIFY_DEVICE_DATA structure. If the NomimalMediaRotationRate is set to 1, this disk is considered a SSD. The latest SSDs will respond to the command by setting word 217 (which is used for reporting the nominal media rotation rate to 1). The word 217 was introduced in 2007 in the ATA8-ACS specification.
Upvotes: 13