Getting The Hard Drive Serial Number With VBA

I was trying to help in the following Answers forum thread

In which Wahedi is inquirying about retrieving the HDD serial number.

I knew I had such code stored away because I had done this on a personal project many years ago.  I also knew I had previously provided code to retrieve the BIOS serial number on this blog which employs the same basic approach.

So I went digging and found 2 functions that might be of interest to some of you out there.

Enumerating The Disk Drives And Their Serial Numbers

The following procedure will enumerate all the Disk Drive(s) Serial Number(s).

'---------------------------------------------------------------------------------------
' Procedure : GetDDSerialNumber
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Retrieve the HDD Serial Number(s)
' 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: Uses Late Binding, so none required
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sHost     : Name/IP Address of the PC to query assuming you have the rights to do so
'               optional, so by leaving it blank it will query the local computer
'
' Usage:
' ~~~~~~
' ? GetDDSerialNumber
'       -> 1835_C380_0088_0001_001A_428B_4465_2EE6.,JR800XANXUNJEE
'
' Revision History:
' Rev       Date(yyyy/mm/dd)        Description
' **************************************************************************************
' 1         2018-09-03              Initial Release
'---------------------------------------------------------------------------------------
Function GetDDSerialNumber(Optional sHost As String = ".") As String
    'Win32_DiskDrive -> https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-diskdrive
    On Error GoTo Error_Handler
    Dim oWMI                  As Object    'WMI object to query
    Dim oDDs                As Object
    Dim oDD                 As Object
 
    Set oWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & sHost & "\root\cimv2")
    Set oDDs = oWMI.ExecQuery("SELECT DeviceID, SerialNumber FROM Win32_DiskDrive")
 
    On Error Resume Next
    For Each oDD In oDDs
       'Debug.Print oDD.DeviceID, Trim(oDD.SerialNumber)
       GetDDSerialNumber = GetDDSerialNumber & Trim(oDD.SerialNumber) & ","
       'GetDDSerialNumber = GetDDSerialNumber & oDD.DeviceID & ":" & Trim(oDD.SerialNumber) & ","
    Next
    If Right(GetDDSerialNumber, 1) = "," Then GetDDSerialNumber = Left(GetDDSerialNumber, Len(GetDDSerialNumber) - 1)
 
Error_Handler_Exit:
    On Error Resume Next
    If Not oDD Is Nothing Then Set oDD = Nothing
    If Not oDDs Is Nothing Then Set oDDs = Nothing
    If Not oWMI Is Nothing Then Set oWMI = Nothing
    Exit Function
 
Error_Handler:
    MsgBox "The following error has occurred." & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: GetDDSerialNumber" & vbCrLf & _
           "Error Description: " & Err.Description, _
           vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

 

Retrieving The Serial Number of A Particular Drive Letter

This procedure will return the serial number of the specified drive letter (C:, D:, …, Z:)

'---------------------------------------------------------------------------------------
' Procedure : WMI_GetDriveSerialNumber
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Retrieve the HDD Serial Number(s) for the specified Drive
' 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: Uses Late Binding, so none required
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sDriveLetter  : Drive Letter for which to retrieve the SN for
' sHost         : Name/IP Address of the PC to query assuming you have the rights to do so
'                   optional, so by leaving it blank it will query the local computer
'
' Usage:
' ~~~~~~
'? WMI_GetDriveSerialNumber("C:")
'       -> 1835_C380_0088_0001_001A_428B_4465_2EE6.
'? WMI_GetDriveSerialNumber("D:")
'       -> JR800XANXUNJEE
'
' Revision History:
' Rev       Date(yyyy/mm/dd)        Description
' **************************************************************************************
' 1         2018-09-03              Initial Release
'---------------------------------------------------------------------------------------
Public Function WMI_GetDriveSerialNumber(Optional sDriveLetter As String = "C:", Optional sHost As String = ".") As String
    On Error GoTo Error_Handler
    Dim oWMI                  As Object
    Dim sWMIQuery             As String
    Dim oPartitions           As Object
    Dim oPartition            As Object
    Dim oDrives               As Object
    Dim oDrive                As Object
    
    If Right(sDriveLetter, 1) <> ":" Then sDriveLetter = sDriveLetter & ":"

    Set oWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & sHost & "\root\cimv2")
    sWMIQuery = "ASSOCIATORS OF {Win32_LogicalDisk.DeviceID='" & sDriveLetter & "'} WHERE ResultClass=Win32_DiskPartition"
    Set oPartitions = oWMI.ExecQuery(sWMIQuery)
    For Each oPartition In oPartitions
        sWMIQuery = "ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" & oPartition.DeviceID & "'} WHERE ResultClass=Win32_DiskDrive"
        Set oDrives = oWMI.ExecQuery(sWMIQuery)
        For Each oDrive In oDrives
            With oDrive
                WMI_GetDriveSerialNumber = Trim(.SerialNumber)
            End With
        Next
    Next

Error_Handler_Exit:
    On Error Resume Next
    Set oDrive = Nothing
    Set oDrives = Nothing
    Set oPartition = Nothing
    Set oPartitions = Nothing
    Set oWMI = Nothing
    Exit Function

Error_Handler:
    MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: WMI_GetDriveSerialNumber" & 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

 

Alternate Techniques

I thought I’d quickly just offer a couple alternate techniques that can be used. This isn’t VBA, but I thought might be useful none the less just for plain and simple general knowledge.

Command Prompt

wmic diskdrive get Model, SerialNumber, Size, MediaType

PowerShell

Get-PhysicalDisk | Select-Object Model, SerialNumber, Size, MediaType | Format-Table

 

A Few Resources on the Subject

 
 
You may also like to check out theDBguys blog post on this subject: