VBA – Getting Disk/Drive Information

Computer Hard Drive

Have you ever needed to get some basic disk information via VBA?

In the past, refer to m article:

I’ve shown that FSO gives us easy access to some things:

  • Total Drive Size
  • Drive Available Free Space

That said, as with everything VBA, there are a multitude of ways to accomplish the same task and today I thought I’d share other possible approaches.  You pick the one that best suits your needs.
 

Using WMI

WMI is an exceptional resource and it can get information on just about every aspect of a computer, including the disk drives!

Drive Information

To get some general information about the Drives we can do something like:

'---------------------------------------------------------------------------------------
' Procedure : WMI_DriveSize
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Output a listing of Drives with general info about each to the VBE
'               Immediate Window
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: Late Binding  -> none required
' References:
'
' Usage:
' ~~~~~~
' Call WMI_DriveSize
'
' Revision History:
' Rev       Date(yyyy-mm-dd)        Description
' **************************************************************************************
' 1         2023-02-14              Initial Release
'---------------------------------------------------------------------------------------
Public Function WMI_DriveSize()
    On Error GoTo Error_Handler
    #Const WMI_EarlyBind = True    'True => Early Binding / False => Late Binding
    #If WMI_EarlyBind = True Then
        Dim oWMI              As WbemScripting.SWbemServices
        Dim oCols             As WbemScripting.SWbemObjectSet
        Dim oCol              As WbemScripting.SWbemObject
    #Else
        Dim oWMI              As Object
        Dim oCols             As Object
        Dim oCol              As Object
        Const wbemFlagReturnImmediately = 16    '(&H10)
        Const wbemFlagForwardOnly = 32          '(&H20)
    #End If
    Dim sWMIQuery             As String         'WMI Query

    Set oWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
    sWMIQuery = "SELECT * FROM Win32_DiskDrive"
    Set oCols = oWMI.ExecQuery(sWMIQuery, , wbemFlagReturnImmediately Or wbemFlagForwardOnly)
    Debug.Print "Caption", , "Description", "Media Type", , "Serial Number", , "Size"
    Debug.Print String(100, "-")
    For Each oCol In oCols
        Debug.Print oCol.Caption, oCol.Description, oCol.MediaType, oCol.SerialNumber, ConvertBytes(oCol.Size, Megabytes)
    Next
    
    WMI_DriveSize = ""

Error_Handler_Exit:
    On Error Resume Next
    Set oCol = Nothing
    Set oCols = Nothing
    Set oWMI = Nothing
    Exit Function

Error_Handler:
    MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: WMI_DriveSize" & vbCrLf & _
           "Error Description: " & Err.Description & _
           Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
           , vbOKOnly + vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

and this will return something along the lines of:

Caption                     Description   Media Type                  Serial Number               Size
----------------------------------------------------------------------------------------------------
WDC PC SN720 SDAPNTW-512G   Disk drive    Fixed hard disk media       1837_C380_0088_0001_001B_448B_4465_2EE6.   488382.275390625 
HGST HTS721010A9E630        Disk drive    Fixed hard disk media             JR100XBNJUNJEE                       953867.219238281 

Disk Information

We can just as easily retrieve Disk information! We would do something like:

'---------------------------------------------------------------------------------------
' Procedure : WMI_GetDiskInfo
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Output a listing of Disks with general info about each to the VBE
'               Immediate Window
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: Late Binding  -> none required
' References:
'
' Usage:
' ~~~~~~
' Call WMI_GetDiskInfo
'
' Revision History:
' Rev       Date(yyyy-mm-dd)        Description
' **************************************************************************************
' 1         2023-02-14              Initial Release
'---------------------------------------------------------------------------------------
Public Function WMI_GetDiskInfo()
    On Error GoTo Error_Handler
    #Const WMI_EarlyBind = True    'True => Early Binding / False => Late Binding
    #If WMI_EarlyBind = True Then
        Dim oWMI              As WbemScripting.SWbemServices
        Dim oCols             As WbemScripting.SWbemObjectSet
        Dim oCol              As WbemScripting.SWbemObject
    #Else
        Dim oWMI              As Object
        Dim oCols             As Object
        Dim oCol              As Object
        Const wbemFlagReturnImmediately = 16    '(&H10)
        Const wbemFlagForwardOnly = 32          '(&H20)
    #End If
    Dim sWMIQuery             As String         'WMI Query

    Set oWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
    sWMIQuery = "SELECT * FROM Win32_LogicalDisk WHERE MediaType=12"
    Set oCols = oWMI.ExecQuery(sWMIQuery, , wbemFlagReturnImmediately Or wbemFlagForwardOnly)
    Debug.Print "Caption", "Description", , "Media Type", "Size", "Free Space", "% Free"
    Debug.Print String(100, "-")
    For Each oCol In oCols
'        Debug.Print oCol.Caption, oCol.Description, oCol.MediaType, oCol.Size, oCol.FreeSpace, FormatPercent(oCol.FreeSpace / oCol.Size, 2)
        Debug.Print oCol.Caption, oCol.Description, oCol.MediaType, oCol.Size, oCol.FreeSpace, FormatNumber(oCol.FreeSpace / oCol.Size * 100, 2, vbTrue)
    Next

Error_Handler_Exit:
    On Error Resume Next
    Set oCol = Nothing
    Set oCols = Nothing
    Set oWMI = Nothing
    Exit Function

Error_Handler:
    MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: WMI_GetDiskInfo" & vbCrLf & _
           "Error Description: " & Err.Description & _
           Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
           , vbOKOnly + vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

which in turn will return something along the lines of:

Caption       Description                 Media Type    Size          Free Space    % Free
----------------------------------------------------------------------------------------------------
C:            Local Fixed Disk             12           510716276736  43145408512   8.45
D:            Local Fixed Disk             12           977635635200  59698876416   6.11
M:            Local Fixed Disk             12           429481787392  200005386240  46.57

Disk Size

The above is great for a quick overview. Below is an example of how it can be adapted to get the size of a specified Disk.

'---------------------------------------------------------------------------------------
' Procedure : WMI_GetDiskSize
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Get the size of a disk (in bytes)
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: Late Binding  -> none required
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sDisk     : Disk to get the total size/capacity of
'
' Usage:
' ~~~~~~
' ? WMI_GetDiskSize("C")
'   Returns -> 51071627673600
'
' Revision History:
' Rev       Date(yyyy-mm-dd)        Description
' **************************************************************************************
' 1         2023-02-14              Initial Release
'---------------------------------------------------------------------------------------
Public Function WMI_GetDiskSize(sDisk As String) As Double
    On Error GoTo Error_Handler
    #Const WMI_EarlyBind = True    'True => Early Binding / False => Late Binding
    #If WMI_EarlyBind = True Then
        Dim oWMI              As WbemScripting.SWbemServices
        Dim oCols             As WbemScripting.SWbemObjectSet
        Dim oCol              As WbemScripting.SWbemObject
    #Else
        Dim oWMI              As Object
        Dim oCols             As Object
        Dim oCol              As Object
        Const wbemFlagReturnImmediately = 16    '(&H10)
        Const wbemFlagForwardOnly = 32          '(&H20)
    #End If
    Dim sWMIQuery             As String         'WMI Query
    
    If Right(sDisk, 1) <> ":" Then sDisk = sDisk & ":"

    Set oWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
    sWMIQuery = "SELECT * FROM Win32_LogicalDisk WHERE Caption = '" & sDisk & "'"
    Set oCols = oWMI.ExecQuery(sWMIQuery, , wbemFlagReturnImmediately Or wbemFlagForwardOnly)
    For Each oCol In oCols
        WMI_GetDiskSize = FormatNumber(oCol.Size * 100, 2, vbTrue)
        Exit For
    Next

Error_Handler_Exit:
    On Error Resume Next
    Set oCol = Nothing
    Set oCols = Nothing
    Set oWMI = Nothing
    Exit Function

Error_Handler:
    MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: WMI_GetDiskSize" & vbCrLf & _
           "Error Description: " & Err.Description & _
           Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
           , vbOKOnly + vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

and then you can call it by simply doing:

? WMI_GetDiskSize("C")

which returns a value like:

51071627673600

Disk Free Space

Similarly, we can retrieve the Free Space on a disk. The code for that could look a little like:

'---------------------------------------------------------------------------------------
' Procedure : API_GetDiskFreeSpace
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Get the amount of Free Disk space in bytes, or as a percentage of the total
'               disk size
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs:  Late Binding  -> none required
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sDisk     : Drive to get the size of, C: or C:\
'               You can provide a path, but it always return the size of the drive.
' sFormat   : Optional - Specify the desired output format
'               "Number"  => available free space in bytes
'               "Percent" => available free space as a percentage of the total disk size
'
' Usage:
' ~~~~~~
' ? WMI_GetDiskFreeSpace("C")
'   Returns -> 43145740288 which is the number of bytes free on the drive
'
' ? WMI_GetDiskFreeSpace("C", "Percent")
'   Returns -> 8.12 which is the % free space on the disk
'
' Revision History:
' Rev       Date(yyyy-mm-dd)        Description
' **************************************************************************************
' 1         2023-02-13              Initial Release
'---------------------------------------------------------------------------------------
Public Function WMI_GetDiskFreeSpace(sDisk As String, Optional sFormat As String = "Number") As Double
    On Error GoTo Error_Handler
    #Const WMI_EarlyBind = True    'True => Early Binding / False => Late Binding
    #If WMI_EarlyBind = True Then
        Dim oWMI              As WbemScripting.SWbemServices
        Dim oCols             As WbemScripting.SWbemObjectSet
        Dim oCol              As WbemScripting.SWbemObject
    #Else
        Dim oWMI              As Object
        Dim oCols             As Object
        Dim oCol              As Object
        Const wbemFlagReturnImmediately = 16    '(&H10)
        Const wbemFlagForwardOnly = 32          '(&H20)
    #End If
    Dim sWMIQuery             As String         'WMI Query
    
    If Right(sDisk, 1) <> ":" Then sDisk = sDisk & ":"

    Set oWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
    sWMIQuery = "SELECT * FROM Win32_LogicalDisk WHERE Caption = '" & sDisk & "'"
    Set oCols = oWMI.ExecQuery(sWMIQuery, , wbemFlagReturnImmediately Or wbemFlagForwardOnly)
    For Each oCol In oCols
        If sFormat = "Number" Then      'Return the number of bytes
            WMI_GetDiskFreeSpace = oCol.FreeSpace
        ElseIf sFormat = "Percent" Then 'Return the percentage value
            WMI_GetDiskFreeSpace = FormatNumber(oCol.FreeSpace / oCol.Size * 100, 2, vbTrue)
        End If
        Exit For
    Next

Error_Handler_Exit:
    On Error Resume Next
    Set oCol = Nothing
    Set oCols = Nothing
    Set oWMI = Nothing
    Exit Function

Error_Handler:
    MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: WMI_GetDiskFreeSpace" & vbCrLf & _
           "Error Description: " & Err.Description & _
           Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
           , vbOKOnly + vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

which you can call by simply doing:

? WMI_GetDiskFreeSpace("C")

which return the free space in bytes, such as:

43145740288

OR

You can call it by doing:

? WMI_GetDiskFreeSpace("C", "Percent")

which return the free space as a percentage of the toatl capacity, such as:

8.12

 

Using An API

Yes, there are API that we can also use to get Disk/Drive information.

Disk Size

#If VBA7 Then
    Private Declare PtrSafe Function GetDiskFreeSpace Lib "kernel32" Alias "GetDiskFreeSpaceA" (ByVal lpRootPathName As String, lpSectorsPerCluster As Long, lpBytesPerSector As Long, lpNumberOfFreeClusters As Long, lpTotalNumberOfClusters As Long) As Long
#Else
    Private Declare Function GetDiskFreeSpace Lib "kernel32" Alias "GetDiskFreeSpaceA" (ByVal lpRootPathName As String, lpSectorsPerCluster As Long, lpBytesPerSector As Long, lpNumberOfFreeClusters As Long, lpTtoalNumberOfClusters As Long) As Long
#End If

'---------------------------------------------------------------------------------------
' Procedure : API_GetDiskSize
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Get the Disk size in bytes using the GetDiskFreeSpace API
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: None required
' Dependencies: GetDiskFreeSpace API Declaration
' References:
'   https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getdiskfreespacea
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sDrive    : Drive to get the size of, C: or C:\
'               You can provide a path, but it always return the size of the drive.
'
' Usage:
' ~~~~~~
' ? API_GetDiskSize("C:\")
'   Returns -> 510716276736
'
' Revision History:
' Rev       Date(yyyy-mm-dd)        Description
' **************************************************************************************
' 1         2023-02-13              Initial Release
'---------------------------------------------------------------------------------------
Function API_GetDiskSize(sDrive As String) As Double
On Error GoTo Error_Handler
    Dim lRetVal                     As Long
    Dim lSectorsPerCluster          As Long
    Dim lBytesPerSector             As Long
    Dim lNumberOfFreeClusters       As Long
    Dim lTotalNumberOfClusters      As Long

    If Len(sDrive) = 1 Then sDrive = sDrive & ":\"
    If Right(sDrive, 1) = ":" Then sDrive = sDrive & "\" ' Not strictly necessary
    
    lRetVal = GetDiskFreeSpace(sDrive, lSectorsPerCluster, lBytesPerSector, _
                               lNumberOfFreeClusters, lTotalNumberOfClusters)
    If lRetVal = 0 Then
        'Error with API!
    Else
        'x1.000 to get around math issue! Yes, there are different ways to handle this.
        API_GetDiskSize = 1# * lTotalNumberOfClusters * lSectorsPerCluster * lBytesPerSector
    End If
    
Error_Handler_Exit:
    On Error Resume Next
    Exit Function
 
Error_Handler:
    MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
           "Error Source: API_GetDiskSize" & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Description: " & Err.Description & _
           Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
           , vbOKOnly + vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

which we call by doing:

? API_GetDiskSize("C:\")

and that returns

510716276736

Disk Free Space

#If VBA7 Then
    Private Declare PtrSafe Function GetDiskFreeSpace Lib "kernel32" Alias "GetDiskFreeSpaceA" (ByVal lpRootPathName As String, lpSectorsPerCluster As Long, lpBytesPerSector As Long, lpNumberOfFreeClusters As Long, lpTotalNumberOfClusters As Long) As Long
#Else
    Private Declare Function GetDiskFreeSpace Lib "kernel32" Alias "GetDiskFreeSpaceA" (ByVal lpRootPathName As String, lpSectorsPerCluster As Long, lpBytesPerSector As Long, lpNumberOfFreeClusters As Long, lpTtoalNumberOfClusters As Long) As Long
#End If

'---------------------------------------------------------------------------------------
' Procedure : API_GetDiskFreeSpace
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Get the amount of Free Disk space in bytes, or as a percentage of the total
'               disk size using the GetDiskFreeSpace API
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: None required
' Dependencies: GetDiskFreeSpace API Declaration
' References:
'   https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getdiskfreespacea
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sDrive    : Drive to get the size of, C: or C:\
'               You can provide a path, but it always return the size of the drive.
' sFormat   : Optional - Specify the desired output format
'               "Number"  => available free space in bytes
'               "Percent" => available free space as a percentage of the total disk size
'
' Usage:
' ~~~~~~
' ? API_GetDiskFreeSpace("C:\")
'   Returns -> 43483856896
'
' ? API_GetDiskFreeSpace("C:\", "Percent")
'   Returns -> 0.08514287634987
'
' Revision History:
' Rev       Date(yyyy-mm-dd)        Description
' **************************************************************************************
' 1         2023-02-13              Initial Release
'---------------------------------------------------------------------------------------
Function API_GetDiskFreeSpace(sDrive As String, Optional sFormat As String = "Number") As Double
On Error GoTo Error_Handler
    Dim lRetVal                     As Long
    Dim lSectorsPerCluster          As Long
    Dim lBytesPerSector             As Long
    Dim lNumberOfFreeClusters       As Long
    Dim lTotalNumberOfClusters      As Long

    lRetVal = GetDiskFreeSpace(sDrive, lSectorsPerCluster, lBytesPerSector, _
                               lNumberOfFreeClusters, lTotalNumberOfClusters)
    If lRetVal = 0 Then
        'Error with API!
    Else
        'x1.000 to get around math issue! Yes, there are different ways to handle this.
        If sFormat = "Number" Then      'Return the number of bytes
            API_GetDiskFreeSpace = 1# * lNumberOfFreeClusters * lSectorsPerCluster * lBytesPerSector
        ElseIf sFormat = "Percent" Then 'Return the percentage value
            API_GetDiskFreeSpace = (1# * lNumberOfFreeClusters * lSectorsPerCluster * lBytesPerSector) / _
                                   (1# * lTotalNumberOfClusters * lSectorsPerCluster * lBytesPerSector)
        End If
    End If
    
Error_Handler_Exit:
    On Error Resume Next
    Exit Function
 
Error_Handler:
    MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
           "Error Source: API_GetDiskFreeSpace" & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Description: " & Err.Description & _
           Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
           , vbOKOnly + vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

that we call by doing:

? API_GetDiskFreeSpace("C:\")

and that will return (in bytes)

43483856896

OR

by doing:

? API_GetDiskFreeSpace("C:\", "Percent")

and that will return (in percentage of the total capacity of the disk)

0.08514287634987

 

Using WMIC

We can also use good old DOS/Command Prompt commands.

Disk Size

'---------------------------------------------------------------------------------------
' Procedure : WMIC_GetDiskSize
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Get the Disk size in bytes using WMIC
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: None required
' References:
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sDrive    : Drive to get the size of, formatted as => C or C: or C:\
'
' Usage:
' ~~~~~~
' ? WMIC_GetDiskSize("C:")
'   Returns -> 510716276736
'
' Revision History:
' Rev       Date(yyyy-mm-dd)        Description
' **************************************************************************************
' 1         2023-02-13              Initial Release
'---------------------------------------------------------------------------------------
Function WMIC_GetDiskSize(sDrive As String) As Double
    On Error GoTo Error_Handler
    Dim sResult               As String
    Dim aResult               As Variant
    Dim i As Long
    
    If Right(sDrive, 1) = "\" Then sDrive = Left(sDrive, Len(sDrive) - 1)
    If Right(sDrive, 1) <> ":" Then sDrive = sDrive & ":"

    CreateObject("Wscript.Shell").Run "cmd /c wmic logicaldisk " & sDrive & " get size | clip", 0, True
    'Retrieve the results from the clipboard
    With CreateObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
        .GetFromClipboard
        sResult = .GetText
    End With
    'Breakdown the results, line by line
    aResult = Split(sResult, vbCrLf)
    If UBound(aResult) > 1 Then
        For i = 0 To UBound(aResult)
            If IsNumeric(aResult(i)) = True Then
                WMIC_GetDiskSize = aResult(i)
                Exit For
            End If
        Next i
    End If

Error_Handler_Exit:
    On Error Resume Next
    Exit Function

Error_Handler:
    MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: WMIC_GetDiskSize" & vbCrLf & _
           "Error Description: " & Err.Description & _
           Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
           , vbOKOnly + vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

which we call by doing:

? WMIC_GetDiskSize("C:")

and that returns

510716276736

Disk Free Space

'---------------------------------------------------------------------------------------
' Procedure : WMIC_GetDiskFreeSpace
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Get the amount of Free Disk space in bytes using WMIC
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: None required
' References:
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sDrive    : Drive to get the available free space of, formatted as => C or C: or C:\
'
' Usage:
' ~~~~~~
' ? WMIC_GetDiskFreeSpace("C:")
'   Returns -> 43483856896
'
' Revision History:
' Rev       Date(yyyy-mm-dd)        Description
' **************************************************************************************
' 1         2023-02-13              Initial Release
'---------------------------------------------------------------------------------------
Function WMIC_GetDiskFreeSpace(sDrive As String) As Double
    On Error GoTo Error_Handler
    Dim sResult               As String
    Dim aResult               As Variant
    Dim i As Long
    
    If Right(sDrive, 1) = "\" Then sDrive = Left(sDrive, Len(sDrive) - 1)
    If Right(sDrive, 1) <> ":" Then sDrive = sDrive & ":"

    CreateObject("Wscript.Shell").Run "cmd /c wmic logicaldisk " & sDrive & " get freespace | clip", 0, True
    'Retrieve the results from the clipboard
    With CreateObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
        .GetFromClipboard
        sResult = .GetText
    End With
    'Breakdown the results, line by line
    aResult = Split(sResult, vbCrLf)
    If UBound(aResult) > 1 Then
        For i = 0 To UBound(aResult)
            If IsNumeric(aResult(i)) = True Then
                WMIC_GetDiskFreeSpace = aResult(i)
                Exit For
            End If
        Next i
    End If

Error_Handler_Exit:
    On Error Resume Next
    Exit Function

Error_Handler:
    MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: WMIC_GetDiskFreeSpace" & vbCrLf & _
           "Error Description: " & Err.Description & _
           Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
           , vbOKOnly + vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

that we call by doing:

? WMIC_GetDiskFreeSpace("C:")

and that will return (in bytes)

43483856896

 

Summary

I hope this sheds a little light onto all the possibilities VBA offers us to gather information about a PC’s disk drives, such as:

  • FSO
  • WMI
  • API
  • WMIC

and know that there a several other possible approaches!

For instance, we could also, just as easily, automate PowerShell to gather the information using simple commands like:

Get-Volume  | ? {$_. DriveLetter -eq 'C'} | Select-Object Size

and

Get-Volume  | ? {$_. DriveLetter -eq 'C'} | Select-Object SizeRemaining

So, so many possibilities!!!

As always, you are the master of your program, so the choice is yours!
 

Useful Resources