Solved

USB Flash Drive Serial Numbers

Posted on 2013-05-28
9
3,854 Views
Last Modified: 2013-06-30
I am writing a program using Delphi 6 which I would like to run from a USB flash drive and I want to record the serial number of each flash drive when the software is copied to it for the first time.  When the program is opened I want to compare the serial number of the flash drive to the one I recorded when the flash drive software was created.  I don't want the serial number of the drive's volume when formatted.  This is the hardware serial number.  I have found a couple of methods that work but they fail when Vista/Windows 7/8 is used.
0
Comment
Question by:axp275
9 Comments
 
LVL 25

Expert Comment

by:Sinisa Vuk
ID: 39202658
0
 

Author Comment

by:axp275
ID: 39202822
That link will get me the volume s/n.  That changes with each format so it won't work.  Thanks.
0
 
LVL 25

Expert Comment

by:Sinisa Vuk
ID: 39203105
This is serial number !! Best you can find.
http://www.codeproject.com/Articles/6077/How-to-Retrieve-the-REAL-Hard-Drive-Serial-Number
http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_22787299.html
Did you try to format usb device? Volume number is changing and is 8 hex numbers.
Go download this tool and check by yourself:
http://www.popsoftdownload.com/usbphysic-unlimited-site-license-download-113467.html
0
 

Author Comment

by:axp275
ID: 39203803
None of those solutions work for me and I have seen them a very long time ago.  I have solved this puzzle.  see code below:


function GetFlashDriveSerialNumber(const Drive:AnsiChar):string;
var
      FSWbemLocator            :OleVariant;
  objWMIService            :OLEVariant;
  colDiskDrives            :OLEVariant;
  colLogicalDisks      :OLEVariant;
  colPartitions            :OLEVariant;
  objDiskDrive            :OLEVariant;
  objPartition            :OLEVariant;
  objLogicalDisk      :OLEVariant;
  oEnumDiskDrive      :IEnumvariant;
  oEnumPartition      :IEnumvariant;
  oEnumLogical            :IEnumvariant;
  iValue                              :LongWord;
  DeviceID                        :String;
begin;
  Result:='';
  FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
  objWMIService := FSWbemLocator.ConnectServer('.', 'root\CIMV2', '', '');
  colDiskDrives := objWMIService.ExecQuery('SELECT * FROM Win32_DiskDrive WHERE InterfaceType="USB"','WQL',0);
  oEnumDiskDrive:= IUnknown(colDiskDrives._NewEnum) as IEnumVariant;
  while oEnumDiskDrive.Next(1, objDiskDrive, iValue) = 0 do
  begin
            DeviceID        := StringReplace(VarStrNull(objDiskDrive.DeviceID),'\','\\',[rfReplaceAll]); //Escape the `\` chars in the DeviceID value because the '\' is a reserved character in WMI.
            colPartitions   := objWMIService.ExecQuery(Format('ASSOCIATORS OF {Win32_DiskDrive.DeviceID="%s"} WHERE AssocClass = Win32_DiskDriveToDiskPartition',[DeviceID]));//link the Win32_DiskDrive class with the Win32_DiskDriveToDiskPartition class
            oEnumPartition  := IUnknown(colPartitions._NewEnum) as IEnumVariant;
            while oEnumPartition.Next(1, objPartition, iValue) = 0 do
            begin
                  colLogicalDisks := objWMIService.ExecQuery('ASSOCIATORS OF {Win32_DiskPartition.DeviceID="'+VarStrNull(objPartition.DeviceID)+'"} WHERE AssocClass = Win32_LogicalDiskToPartition'); //link the Win32_DiskPartition class with theWin32_LogicalDiskToPartition class.
                  oEnumLogical  := IUnknown(colLogicalDisks._NewEnum) as IEnumVariant;
                  while oEnumLogical.Next(1, objLogicalDisk, iValue) = 0 do
                  begin
                        if SameText(VarStrNull(objLogicalDisk.DeviceID),Drive+':')  then //compare the device id
                        begin
                              Result:=VarStrNull(objDiskDrive.PnPDeviceID);
                              if AnsiStartsText('USBSTOR', Result) then
                              begin
                                    iValue:=LastDelimiter('\', Result);
                                    Result:=Copy(Result, iValue+1, Length(Result));
                              end;//if
                              objLogicalDisk:=Unassigned;
                              Exit;
                        end;//if
                        objLogicalDisk:=Unassigned;
                  end;//while
                  objPartition:=Unassigned;
            end;//while
            objDiskDrive:=Unassigned;
  end;//while
end;
0
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

Author Comment

by:axp275
ID: 39204817
I've requested that this question be closed as follows:

Accepted answer: 0 points for axp275's comment #a39203803

for the following reason:

After I posted my problem I discovered a solution that did exactly what I needed it to do and I have posted the code above.  I don't deserve any points for this because I am using code from an example I found.  I have only adjusted it to compile properly and work for my project.  Thanks to all of those who assisted.
0
 
LVL 25

Accepted Solution

by:
Sinisa Vuk earned 500 total points
ID: 39203817
This code you provide is exact the same as is on page which I suggested:
http://stackoverflow.com/questions/4292395/how-to-get-manufacturer-serial-number-of-an-usb-flash-drive
0
 
LVL 8

Expert Comment

by:lomo74
ID: 39204036
try the following code (translated from http://oroboro.com/usb-serial-number/).
you will need JVCL, Jcl and PerlRegEx libraries, too.
Jcl / JVCL : http://sourceforge.net/projects/jvcl/files/JVCL%203/JVCL%203.47/JVCL347CompleteJCL241-Build4571.zip/download
PerlRegEx : http://www.regular-expressions.info/delphi.html
program usbsn;

{$APPTYPE CONSOLE}

uses
  SysUtils, Windows, JvSetupApi, PerlRegEx;

type
  DEVICE_TYPE = DWORD;
  STORAGE_DEVICE_NUMBER = record
    //
    // The FILE_DEVICE_XXX type for this device.
    //
    DeviceType: DEVICE_TYPE;
    //
    // The number of this device
    //
    DeviceNumber: DWORD;
    //
    // If the device is partitionable, the partition number of the device.
    // Otherwise -1
    //
    PartitionNumber: DWORD;
  end;

const
  FILE_ANY_ACCESS                     = 0;
  METHOD_BUFFERED                     = 0;
  FILE_DEVICE_MASS_STORAGE            = $0000002D;
  IOCTL_STORAGE_BASE                  = FILE_DEVICE_MASS_STORAGE;
  IOCTL_STORAGE_GET_DEVICE_NUMBER     = (IOCTL_STORAGE_BASE shl 16) or (FILE_ANY_ACCESS shl 14) or
                                        ($0420 shl 2) or METHOD_BUFFERED;
  GUID_DEVINTERFACE_USB_DISK: TGUID = (
    D1: $53f56307;
    D2: $b6bf;
    D3: $11d0;
    D4: ($94, $f2, $00, $a0, $c9, $1e, $fb, $8b);
  );

function getDeviceNumber(deviceHandle: THandle): DWORD;
var
  sdn: STORAGE_DEVICE_NUMBER;
  dwBytesReturned: DWORD;
begin
  sdn.DeviceNumber := MAXDWORD;
  dwBytesReturned := 0;
  if not DeviceIoControl(deviceHandle, IOCTL_STORAGE_GET_DEVICE_NUMBER,
  nil, 0, @sdn, SizeOf(sdn), dwBytesReturned, nil) then
   // handle error - like a bad handle.
    Result := MAXDWORD
  else
    Result := sdn.DeviceNumber;
end;

function getDeviceSerialNumber(vol: Char): string;
var
  devicePath: string;
  deviceHandle: THandle;
  volumeDeviceNumber: DWORD;
  hDev: HDEVINFO;
  Buf: array[0..1023] of Byte;
  pspdidd: PSPDeviceInterfaceDetailData;
  spdid: SP_DEVICE_INTERFACE_DATA;
  spdd: SP_DEVINFO_DATA;
  dwIndex, dwSize: DWORD;
  res: LongBool;
  hDrive: THandle;
  usbDeviceNumber: DWORD;
  re: TPerlRegEx;
begin
  // get the device handle
  devicePath := '\\.\' + vol + ':';

  deviceHandle := CreateFile(PChar(devicePath), 0,
    FILE_SHARE_READ or FILE_SHARE_WRITE, nil,
    OPEN_EXISTING, 0, 0);
  if deviceHandle = INVALID_HANDLE_VALUE then
    Exit;

  // to get the device number
  volumeDeviceNumber := getDeviceNumber(deviceHandle);
  CloseHandle(deviceHandle);

  // Get device interface info set handle
  // for all devices attached to the system
  hDev := SetupDiGetClassDevs(
    @GUID_DEVINTERFACE_USB_DISK, nil, 0,
    DIGCF_PRESENT or DIGCF_DEVICEINTERFACE);

  if hDev = HDEVINFO(INVALID_HANDLE_VALUE) then
    Exit;

  // Get a context structure for the device interface
  // of a device information set.
  Cardinal(pspdidd) := Cardinal(@Buf);

  spdid.cbSize := SizeOf(spdid);

  dwIndex := 0;
  while True do begin
    if not SetupDiEnumDeviceInterfaces(hDev, nil,
    GUID_DEVINTERFACE_USB_DISK, dwIndex, spdid) then
       Break;

    dwSize := 0;
    SetupDiGetDeviceInterfaceDetail(hDev, @spdid, nil,
      0, dwSize, nil);

    if (dwSize <> 0) and (dwSize <= SizeOf(Buf)) then begin
      pspdidd^.cbSize := SizeOf(pspdidd^); // 5 Bytes!

      ZeroMemory(@spdd, SizeOf(spdd));
      spdd.cbSize := SizeOf(spdd);

      res := SetupDiGetDeviceInterfaceDetail(
        hDev, @spdid, pspdidd, dwSize, dwSize, @spdd);
      if res then begin
        hDrive := CreateFile(pspdidd^.DevicePath, 0,
          FILE_SHARE_READ or FILE_SHARE_WRITE,
          nil, OPEN_EXISTING, 0, 0);
        if hDrive <> INVALID_HANDLE_VALUE then begin
          usbDeviceNumber := getDeviceNumber(hDrive);

          if usbDeviceNumber = volumeDeviceNumber then begin
            re := TPerlRegEx.Create;
            re.RegEx := '&rev_[^#]+#([^&#]+)';
            re.Subject := PChar(@pspdidd^.DevicePath);
            if re.Match then begin
              Result := re.Groups[1];
              Exit;
            end;
          end;
        end;
        CloseHandle(hDrive);
      end;
    end;
    Inc(dwIndex);
  end;

  SetupDiDestroyDeviceInfoList(hDev);
end;

begin
  try
    LoadSetupApi;
    Writeln(getDeviceSerialNumber('N'));
    UnloadSetupApi;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

Open in new window

0
 

Author Closing Comment

by:axp275
ID: 39204818
This user did in fact send a link with the same code I used even though I discovered this on my own from a different link so they should get the points for the solution.
0
 

Expert Comment

by:johnnyex
ID: 39288514
sorry again, confused so which solution is best?
here we can see:
http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_28140731.html#a39203803

There we can see two methods:
http://stackoverflow.com/questions/4292395/how-to-get-manufacturer-serial-number-of-an-usb-flash-drive


Where author says: "UPDATE
Some drivers of the USB disks does not expose the manufacturer serial number on the Win32_DiskDrive.SerialNumber property, so on this cases you can extract the serial number from the PnPDeviceID property."


So which one is the best method which will work on all drives or maybe use two hybrid if one fail?

Would be good to have one solid solution which will just work is this from first link I posted or second method from stackoverflow link?
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Suggested Solutions

This article will show, step by step, how to integrate R code into a R Sweave document
Although it can be difficult to imagine, someday your child will have a career of his or her own. He or she will likely start a family, buy a home and start having their own children. So, while being a kid is still extremely important, it’s also …
An introduction to basic programming syntax in Java by creating a simple program. Viewers can follow the tutorial as they create their first class in Java. Definitions and explanations about each element are given to help prepare viewers for future …
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now