18

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?

Peter O.
  • 32,158
  • 14
  • 82
  • 96
Khaleel Hmoz
  • 987
  • 2
  • 13
  • 24
  • You could maintain a list of hardware identifiers of SSD drives, and check against that. Sure, that is an evolving list... – ppeterka Dec 05 '12 at 15:28
  • 2
    +1 for getting beat up. I could see how you might use this to flop between a memory or disk based approach. It takes time to measure access time. – paparazzo Dec 05 '12 at 15:57
  • Hybrid drives are a lost cause as well. Got one in my new laptop, the C: drive is a hard disk with a 20 GB SSD. This is just not a problem that ever needs to be solved. – Hans Passant Dec 05 '12 at 16:36
  • 1
    @Blam I do not beat up anyone, I ask a sincere question. There is no fool proof way to detect an SSD, but there are ways to measure latency and throughput. If OP wants to make decisions based on that (as not to exclude hybrid drives and future fast storage devices (does a USB 3 flash drive count?)), that question should be answered before a helpful answer can be given. – CodeCaster Dec 05 '12 at 16:45
  • I just need to check if the system Particular that contains the current running OS is on SSD hard disk or not without needing any Admin privileges or writing a file. – Khaleel Hmoz Dec 06 '12 at 08:02
  • @CodeCaster You were beating up the OP, for no good reason. Sure your point re hybrid disks is a good one, but "do you really want to know this?" is not a constructive comment. I found this question through wanting to know this exact point (I want to do an audit of a company's PCs and this is a - perfectly valid - question that I want to ask) and found your comment unhelpful. – David Arno May 13 '14 at 10:39
  • @DavidArno thanks for commenting on that one and a half year later. I was just asking OP whether his question was the one he actually wanted answered. Most questions are misguided due to inexperience. Fine, it answered _your_ question, but that doesn't have to have been OP's question. You want to list hardware in computers, OP wants to know whether it's a fast storage. Entirely different. You have the reputation to alter this question into a more clean, factual "reference question" for the actual question you seem to read in it, so please do that instead of replying on old comments. – CodeCaster May 13 '14 at 10:43

3 Answers3

13

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.

Simon Mourier
  • 132,049
  • 21
  • 248
  • 298
  • Problem with this approach is that it won't detect whether a storage is an SSD, but just check if it has low latency and high throughput. Hence my question to OP. :-) – CodeCaster Dec 05 '12 at 16:41
  • 3
    @CodeCaster - I don't agree. It's capable of testing the nominal ATA media rotation rate which should be set to 1 ('non rotating media') for SSD. See http://www.t13.org/documents/UploadedDocuments/docs2007/D1699r4a-ATA8-ACS.pdf page 139, although some SSD disks/drivers could actually not implement this. – Simon Mourier Dec 05 '12 at 17:57
  • 1
    Actually it works fine, and I found this solution before but it still writes a file and needs privilege. – Khaleel Hmoz Dec 06 '12 at 07:42
  • 1
    @KhaleelHmoz - are you using the 'nominal media rotation rate' method (choice 1)? – Simon Mourier Dec 06 '12 at 08:31
  • Yes I tried it, it works fine but I can't use it because it needs privilege to write a file – Khaleel Hmoz Dec 06 '12 at 08:57
  • 1
    Oh, it's not really creating a file, the CreateFile API is used to open the drive to be able to use an API on it, but yes, the 'media rotation method' needs administrative privilege. Have you tried the 'no seek penalty' method? – Simon Mourier Dec 06 '12 at 09:17
9

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

Roman Podymov
  • 4,168
  • 4
  • 30
  • 57
SebA
  • 123
  • 1
  • 4
0

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;
    }
}
O. V.
  • 125
  • 1
  • 8