Skip to content
Bruno Sonnino
Menu
  • Home
  • About
Menu

Getting Disk information in Windows with C#

Posted on 8 April 2022

There are some times when you need to get the disk information in your system, to check what's happening, for inventory check, or even to know the free and available space. Getting the free and available space is fairly easy in .NET, just use the GetDrives method of the DriveInfo class:

DriveInfo[] drives = DriveInfo.GetDrives();

foreach (DriveInfo drive in drives)
{
    Console.WriteLine($"Name: {drive.Name}");
    Console.WriteLine($"VolumeLabel: {drive.VolumeLabel}");
    Console.WriteLine($"RootDirectory: {drive.RootDirectory}");
    Console.WriteLine($"DriveType: {drive.DriveType}");
    Console.WriteLine($"DriveFormat: {drive.DriveFormat}");
    Console.WriteLine($"IsReady: {drive.IsReady}");
    Console.WriteLine($"TotalSize: {drive.TotalSize}");
    Console.WriteLine($"TotalFreeSpace: {drive.TotalFreeSpace}");
    Console.WriteLine($"AvailableFreeSpace: {drive.AvailableFreeSpace}");
    Console.WriteLine();
}
C#

If you run this code, you will get the info for all drives in your system:

This is ok for most apps, but sometimes you want more than that. If, for example, you want an inventory of your physical disks (not the logical disks, like DriveInfo gives) ?

The physical and logical structure of your disks can differ a lot. For example, if you have a disk with three partitions, you will have one physical disk and three logical disks.

On the other side, you can mount a drive in an empty folder and have two physical disks and one logical disk. And we are not considering multiple OSs, here.

.NET doesn't have any dedicated class for the physical disk structure, so we should find another way to do it. In fact, there is a way to get this information in Windows, called WMI (Windows Management Instrumentation).

It's the infrastructure for data management in Windows and you can use it to manage your local and remote systems. You can access it with C++, C# or even PowerShell, to get info and manage your computer.

With WMI, you can use SQL-like queries to query information in your system, using the available classes. For example, to get all the drives in your system, you would use:

SELECT * FROM Win32_DiskDrive
SQL

That would return a key-value set with all the properties of the system disks, and you can check the values you want. You can even filter the properties and drives that you want. Something like:

SELECT DeviceID, Model, Name, Size, Status, Partitions, 
  TotalTracks, TotalSectors, BytesPerSector, SectorsPerTrack, TotalCylinders, TotalHeads, 
  TracksPerCylinder, CapabilityDescriptions 
  FROM Win32_DiskDrive WHERE MediaType = 'Fixed hard disk media'
SQL

Will get only the device data and geometry for the fixed disks in your system (it won't get info for the external HDs).

Now that we already know how to get the disk information, let's see how to do it in C#.

To use WMI in a C# program, we must add the package System.Management to the project and start using it.

Open a new terminal window and create a new console application with

dotnet new console -o DiskInfoCSharp
PowerShell

Once you do that, a new console project will be created in the DiskInfoCSharp folder. You can cd to it and add the new package to the project with

dotnet add package System.Management
PowerShell

This will add the package to the project and will allow you to use WMI in it. You can open VS Code with code . and start editing the project.

The first step is to create a scope and connect to it:

using System.Management;

ManagementScope scope = new ManagementScope("\\\\.\\root\\cimv2");
scope.Connect();
C#

This will allow you to query data in the local computer. If you want to connect to a remote computer, just change the \. to the name of the remote computer.

Then, you must create the query for getting the disk information:

ObjectQuery query = new ObjectQuery(@"SELECT DeviceID, Model, Name, Size, Status, Partitions, 
  TotalTracks, TotalSectors, BytesPerSector, SectorsPerTrack, TotalCylinders, TotalHeads, 
  TracksPerCylinder, CapabilityDescriptions 
  FROM Win32_DiskDrive WHERE MediaType = 'Fixed hard disk media'");
C#

As you can see, the query has a syntax similar to SQL, you can change it to get different fields (or use * to get all fields) or change (or remove) the WHERE clause. This query will only return the selected fields for the fixed hard disks.

Then, we should instantiate a ManagementObjectSearcher object and start iterating on all instances of fixed disks in your system:

ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
foreach (ManagementObject wmi_HD in searcher.Get())
{
    foreach (PropertyData property in wmi_HD.Properties)
        Console.WriteLine($"{property.Name} = {property.Value}");
    var capabilities = wmi_HD["CapabilityDescriptions"] as string[];
    if (capabilities != null)
    {
        Console.WriteLine("Capabilities");
        foreach (var capability in capabilities)
            Console.WriteLine($"  {capability}");
    }
    Console.WriteLine("-----------------------------------");
}
C#

For each disk, we get all the properties and then we iterate on the capability descriptions, as this is a property that returns an array of strings.

If we run this program, we will get something like

As you can see, it's very easy to get disk information using WMI in C#. There are some caveats in using this method:

  • You don't have the properties in advance. Yes, you could create a class with the properties and populate it, but it's not something that is built in
  • This method only works in Windows. If you are creating a multi-platform program, this method isn't for you

On the other side, this is a very easy method to get the information in local and remote computers, you can easily filter data and use it as you want.

If you go to the Using WMI page, you will see a note:

As you can see, the System.Management namespace is not recommended anymore, and it must be replaced by the Microsoft.Management.Infrastructure, especially for .NET Core apps.

To port our app, the first thing to do is to ass the package Microsoft.Management.Infrastructure with

dotnet add package Microsoft.Management.Infrastructure
PowerShell

Once you do that, you should change the classes you are using to access the data. We create a CimSession and query the data with QueryInstances:

using Microsoft.Management.Infrastructure;

var instances = CimSession.Create(null)
                .QueryInstances(@"root\cimv2", "WQL", @"SELECT DeviceID, Model, Name, Size, Status, Partitions, 
   TotalTracks, TotalSectors, BytesPerSector, SectorsPerTrack, TotalCylinders, TotalHeads, 
   TracksPerCylinder, CapabilityDescriptions 
   FROM Win32_DiskDrive WHERE MediaType = 'Fixed hard disk media'");
C#

Once you do that, you can iterate on the instances and get the properties with:

foreach (var instance in instances)
{
    foreach (var property in instance.CimInstanceProperties)
        Console.WriteLine($"{property.Name} = {property.Value}");
    var capabilities = instance.CimInstanceProperties["CapabilityDescriptions"].Value as string[];
    if (capabilities != null)
    {
        Console.WriteLine("Capabilities");
        foreach (var capability in capabilities)
            Console.WriteLine($"  {capability}");
    }
    Console.WriteLine("-----------------------------------");
}
C#

If you run the program, you will get properties similar to the ones in the previous figure.

As you can see, WMI can ease the retrieval of information in a Windows machine. Unfortunately, that can't be used in a Linux machine, that may be a subject for another article!

All the code for this article is at https://github.com/bsonnino/WMICsharp

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

  • May 2025
  • December 2024
  • October 2024
  • August 2024
  • July 2024
  • June 2024
  • November 2023
  • October 2023
  • August 2023
  • July 2023
  • June 2023
  • May 2023
  • November 2022
  • October 2022
  • September 2022
  • August 2022
  • June 2022
  • April 2022
  • March 2022
  • February 2022
  • January 2022
  • July 2021
  • June 2021
  • May 2021
  • April 2021
  • March 2021
  • February 2021
  • January 2021
  • December 2020
  • October 2020
  • September 2020
  • April 2020
  • March 2020
  • January 2020
  • November 2019
  • September 2019
  • August 2019
  • July 2019
  • June 2019
  • April 2019
  • March 2019
  • February 2019
  • January 2019
  • December 2018
  • November 2018
  • October 2018
  • September 2018
  • August 2018
  • July 2018
  • June 2018
  • May 2018
  • November 2017
  • October 2017
  • September 2017
  • August 2017
  • June 2017
  • May 2017
  • March 2017
  • February 2017
  • January 2017
  • December 2016
  • November 2016
  • October 2016
  • September 2016
  • August 2016
  • July 2016
  • June 2016
  • May 2016
  • April 2016
  • March 2016
  • February 2016
  • October 2015
  • August 2013
  • May 2013
  • February 2012
  • January 2012
  • April 2011
  • March 2011
  • December 2010
  • November 2009
  • June 2009
  • April 2009
  • March 2009
  • February 2009
  • January 2009
  • December 2008
  • November 2008
  • October 2008
  • July 2008
  • March 2008
  • February 2008
  • January 2008
  • December 2007
  • November 2007
  • October 2007
  • September 2007
  • August 2007
  • July 2007
  • Development
  • English
  • Português
  • Uncategorized
  • Windows

.NET AI Algorithms asp.NET Backup C# Debugging Delphi Dependency Injection Desktop Bridge Desktop icons Entity Framework JSON Linq Mef Minimal API MVVM NTFS Open Source OpenXML OzCode PowerShell Sensors Silverlight Source Code Generators sql server Surface Dial Testing Tools TypeScript UI Unit Testing UWP Visual Studio VS Code WCF WebView2 WinAppSDK Windows Windows 10 Windows Forms Windows Phone WPF XAML Zip

  • Entries RSS
  • Comments RSS
©2025 Bruno Sonnino | Design: Newspaperly WordPress Theme
Menu
  • Home
  • About