Link to home
Start Free TrialLog in
Avatar of timothyspriggs
timothyspriggs

asked on

Problem getting HDD C:\ Drive Serial -- Not as easy a fix as you might think!

Okay, a bunch of you are in here thinking you're going to get a quick 500 points... Not so quick!


Here is the Problem: I have been using the code below in a client's application. The purpose of the code is to get the C:\ Drive's serial number to base a unique ID off of. How we use the Unique ID is not the issue. The issue is that approximately .01 percent of the installs return not "ESB-4321" or whatever the serial might be, but instead return only "0". Now, if this happened every time I would know I did something wrong -- but it only happens in 2-3 out of 1,000 installs. So, what could be causing this? If the case is that some systems are unable to return HDD serial, then the problem is not with the code. But if all systems absolutely return HDD serial, then the problem is in the code, but would be hard to pinpoint since it is so anomalous.

Here is the code I am using:

Public Function GetSerialNumber() As String

    Dim Serial As Long, VName As String, FSName As String, TempSerial As String
   
    'Create buffers
    VName = String$(255, Chr$(0))
    FSName = String$(255, Chr$(0))
   
    'Get the volume information -- yes, I already declared this function in the module
    GetVolumeInformation "C:\", VName, 255, Serial, 0, 0, FSName, 255
   
    'Strip the extra chr$(0)'s
    VName = Left$(VName, InStr(1, VName, Chr$(0)) - 1)
    FSName = Left$(FSName, InStr(1, FSName, Chr$(0)) - 1)
    TempSerial = Trim(Str$(Serial))
   
    GetSerialNumber = TempSerial

End Function


It has also been suggested that I use the FileSystemObject to get the HDD serial, like this (not my code):

Dim fso As New FileSystemObject
Dim drv As Drive
Set drv = fso.GetDrive(fso.GetDriveName("c:"))
MsgBox "Serial number of c: " & drv.SerialNumber

The problem is, if I don't figure out what the problem is with my original code, then I can't assure the client that the problem is fixed just because I used a whole new untested code.




Avatar of vinnyd79
vinnyd79

Are the drives that it fails on SCSI drives as opposed to IDE?
Avatar of Harisha M G
Hi timothyspriggs,
    SCSI drives also have numbers... but they may not return

Bye
---
Harish
Avatar of timothyspriggs

ASKER

Could be, but I have no way of knowing. Do you have a suspicion that could be the problem? Have you ever read of or heard of that being a problem? Now, if that is it, I wonder if there is a way to determin programmatically whether the drive is SCSI or IDE? And if so, is there a way to get a unique ID from a SCSI drive.

Another thought -- could an IDE RAID cause this problem?
>> Another thought -- could an IDE RAID cause this problem?
Likely no
Harish,

I see your point that it may not return a number to GetVolumeInformation -- but surely there has to be a way to get the number -- otherwise, how does the bios know how to boot? And if info is available to the bios, doesn't it also have to be available to Windows through an interface? What I mean is this: when you use Windows to create / format a partition on a SCSI drive, wouldn't you think that Windows has access to the serial numbers?

-- Tim
This is what ALLAPI.NET's API-GUIDE notes about it :

If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call GetLastError.

The getlasterror function is like this :

Const FORMAT_MESSAGE_ALLOCATE_BUFFER = &H100
Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000
Const LANG_NEUTRAL = &H0
Const SUBLANG_DEFAULT = &H1
Private Declare Function GetLastError Lib "kernel32" () As Long
Private Declare Function FormatMessage Lib "kernel32" Alias "FormatMessageA" (ByVal dwFlags As Long, lpSource As Any, ByVal dwMessageId As Long, ByVal dwLanguageId As Long, ByVal lpBuffer As String, ByVal nSize As Long, Arguments As Long) As Long
Private Sub Form_Load()
    Dim Buffer As String
    Buffer = Space(200)
    FormatMessage FORMAT_MESSAGE_FROM_SYSTEM, ByVal 0&, GetLastError, LANG_NEUTRAL, Buffer, 200, ByVal 0&
    MsgBox Buffer
End Sub

Try to catch a detailed message instead of guessing the hardware's installed
Hi
The only reason I can imagine: does user have access to root directory (c:\)? If no, fso'll also fail
Here is the function I use and it works on both SCSI and IDE Drives. (just tested both)  Drive letter is hard coded but that can be changed to meet your needs

Private Declare Function GetVolumeInformation Lib "kernel32" Alias "GetVolumeInformationA" (ByVal lpRootPathName As String, ByVal lpVolumeNameBuffer As String, ByVal nVolumeNameSize As Long, lpVolumeSerialNumber As Long, lpMaximumComponentLength As Long, lpFileSystemFlags As Long, ByVal lpFileSystemNameBuffer As String, ByVal nFileSystemNameSize As Long) As Long

Public Function HardSerial() As Long
    Dim Buf$, Name$, Flags&, Length&
    Dim Serial As Long
    GetVolumeInformation "C:\", Buf$, 255, Serial, Length, Flags, Name$, 255
    HardSerial = Serial
End Function
ASKER CERTIFIED SOLUTION
Avatar of Ark
Ark
Flag of Russian Federation image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
From MSDN:

GetVolumeInformation

lpVolumeSerialNumber
[out] Pointer to a variable that receives the volume serial number.
This parameter can be NULL if the serial number is not required.
Windows 95/98/Me: If the queried volume is a network drive, the serial number will not be returned.
Ark! You are everywhere today! Thanks for stopping by.

Okay, I always ask for Drive C:\ -- I don't think that C:\ can ever be a network drive (though I have been wrong before.) And as for not having access to the logical drive, how can the user not have access to drive C:\? Could it be possible that you have to have administrative privileges just to get the volume serial of your own boot partition?

And Ark, you're going to make feel guilty if you keep answering my questions! I will have to mail you a coupon for beer -- or if you are under 21, root beer.

-- Tim
Thanks for that test, rdwillet. So now we know for sure that it isn't a SCSI problem.
So, the answer is: there is no answer?  :-)