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: