Get the total free volume for each disk via WMI in C#

You need to use WMI to find out how much free space there is on each physical HDD. It is not known in advance how many HDDs are connected and how many partitions are on each disk. I sketched this code.

ManagementObjectSearcher wdSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");

foreach (ManagementObject drive in wdSearcher.Get())
{
    Driver driver = new Driver();
    driver.Model = drive["Model"].ToString().Trim();
    driver.Type = drive["InterfaceType"].ToString().Trim();
    driver.Partitions = byte.Parse(drive["Partitions"].ToString().Trim());
    driver.TotalSpace = long.Parse(drive["Size"].ToString().Trim());
}

ManagementObjectSearcher lgSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_LogicalDisk");

iDriveIndex = 0;
byte partitionCount = 1;

foreach (ManagementObject drive in lgSearcher.Get())
{
    if (iDriveIndex > DriverList.Count) break;

    if (partitionCount > DriverList[iDriveIndex].Partitions)
    {
        iDriveIndex++;
        partitionCount = 1;
    }

    long freeSpace = 0;

    try
    {
        freeSpace = long.Parse(drive["FreeSpace"].ToString().Trim());
    }
    catch
    { continue; }

    DriverList[iDriveIndex].FreeSpace += freeSpace;
    partitionCount++;
}

But the problem is that the Partition variable returns the number 3, taking into account the hidden partitions. And in Win32_LogicalDisk, of course, there are no such sections.

 1
Author: aa_talanin, 2019-02-01

1 answers

Using the Win32_LogicalDiskToPartition class, which allows you to link logical disks and partitions. It is easy to navigate from a partition to a physical disk by index. Something like that:

using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Management;

namespace ConsoleApp1
{    

    class Program
    {

        public struct WmiSelectionCondition
        {
            public string PropertyName { get; set; }
            public string PropertyValue { get; set; }
        }

        public struct LogicalDiskToPartition
        {
            public WmiSelectionCondition PartitionSelectionCondition { get; set; }
            public WmiSelectionCondition LogicalDiskSelectionCondition { get; set; }
        }

        //получает таблицу соответствия логических дисков и разделов
        public static List<LogicalDiskToPartition> GetPartitionMap()
        {
            ManagementObjectSearcher mos = new ManagementObjectSearcher(
                "SELECT Antecedent,Dependent FROM Win32_LogicalDiskToPartition"
                );
            LogicalDiskToPartition item;
            WmiSelectionCondition condition;
            List<LogicalDiskToPartition> list = new List<LogicalDiskToPartition>();
            string text;
            string[] arr, arr2;

            using (mos)
            {
                var moc = mos.Get();                

                foreach (ManagementObject mo in mos.Get())
                {
                    item = new LogicalDiskToPartition();

                    //Распарсим значения ref-полей класса Win32_LogicalDiskToPartition
                    //Они имеют формат Class.Property="Value"

                    text = mo["Antecedent"].ToString(); //Partition reference
                    arr = text.Split(new char[] { '=', '"' }, StringSplitOptions.RemoveEmptyEntries);

                    if (arr.Length >= 2)
                    {
                        arr2 = arr[0].Split(new char[] { ':', '.' }, StringSplitOptions.RemoveEmptyEntries);

                        condition = new WmiSelectionCondition();
                        if (arr2.Length == 0) condition.PropertyName = "";
                        else condition.PropertyName = arr2[arr2.Length - 1];
                        condition.PropertyValue = arr[1];
                        item.PartitionSelectionCondition = condition;
                    }

                    text = mo["Dependent"].ToString(); //Logical disk reference
                    arr = text.Split(new char[] { '=', '"' }, StringSplitOptions.RemoveEmptyEntries);

                    if (arr.Length >= 2)
                    {
                        arr2 = arr[0].Split(new char[] { ':', '.' }, StringSplitOptions.RemoveEmptyEntries);

                        condition = new WmiSelectionCondition();
                        if (arr2.Length == 0) condition.PropertyName = "";
                        else condition.PropertyName = arr2[arr2.Length - 1];
                        condition.PropertyValue = arr[1];
                        item.LogicalDiskSelectionCondition = condition;
                    }

                    list.Add(item);
                }

            }
            return list;
        }

        //выборка значения свойства из WMI-класса по заданному условию
        public static object WmiPerformSelection(string prop_to_select,string classname, WmiSelectionCondition condition )
        {
            ManagementObjectSearcher mos = new ManagementObjectSearcher(
                String.Format(
                "SELECT {0} FROM {1} WHERE {2} = '{3}'",
                prop_to_select, classname, condition.PropertyName, condition.PropertyValue)
                );

            foreach (ManagementObject mo in mos.Get())
            {                
                foreach (var prop in mo.Properties)
                {                    
                    if (prop.Value != null) return prop.Value;                    
                }                
            }
            return null;
        }

        //вычисляет свободное место на диске, заданном индексом
        public static long CalcDriveFreeSpace(List<LogicalDiskToPartition> map, int index)
        {
            long result = 0;

            foreach (var item in map)
            {
                object val = WmiPerformSelection("DiskIndex", "Win32_DiskPartition", item.PartitionSelectionCondition);
                if (val == null) continue;
                int item_index = Convert.ToInt32(val);
                if (item_index != index) continue;

                val = WmiPerformSelection("FreeSpace", "Win32_LogicalDisk", item.LogicalDiskSelectionCondition);
                if (val == null) continue;
                long freespace = Convert.ToInt64(val);
                result += freespace;   
            }

            return result;
        }

        static void Main(string[] args)
        {                
            var map = GetPartitionMap();           

            ManagementObjectSearcher mos = new ManagementObjectSearcher(
               String.Format(
               "SELECT Caption, Index, Size FROM Win32_DiskDrive")
               );

            foreach (ManagementObject mo in mos.Get())
            {
                object val = mo["Index"];
                int index = Convert.ToInt32(val);

                string caption="";
                if (mo["Caption"] != null) caption = mo["Caption"].ToString();

                string size="0";
                if (mo["Size"] != null) size = mo["Size"].ToString();

                long freespace = CalcDriveFreeSpace(map, index);                

                Console.WriteLine("{0}: {1} bytes total; {2} bytes free",caption, size, freespace);                
            }

            Console.ReadKey();
        }

    }
}
 0
Author: MSDN.WhiteKnight, 2019-02-03 19:32:07