Delphi.Boy
Delphi.Boy

Reputation: 1216

Getting Manufacturer, Serial Number, Model from Drive Letter

I'm trying to have some effective code to get vendor, serial number, and model of a USB drive, using its drive letter. I've searched a lot and found several solutions. But I can not determine which one is the best one.

First one is here. Uses hid.pas from JEDI, but I don't know how to use it with a single drive. Specially, function GetHidDeviceInfo is very interesting but requires symbolic link rather that a drive letter. I tried to invite a symbolic link for the drive letter at no avail.

Second one is here. Uses WMI which doesn't seem very clean. My experience tells me that WMI doesn't work on all PCs. The code doesn't work on my own laptop, saying 'The RPC server is unavailable'.

Please advice me on the best way to achieve my goal. Are other ways around?

Update: I'm posting some sample code, combining the results of comments below.

{$APPTYPE CONSOLE}

uses
  Windows, Messages, SysUtils, Variants;

type
  PHIDDAttributes = ^THIDDAttributes;
  HIDD_ATTRIBUTES = record
    Size:          ULONG; // size of structure (set before call)
    VendorID:      Word;
    ProductID:     Word;
    VersionNumber: Word;
    //
    // Additional fields will be added to the end of this structure.
    //
  end;
  THIDDAttributes = HIDD_ATTRIBUTES;

  THIDUSBDeviceInfo = Record   { contains interface level information of each device}
    SymLink            : String;
    BufferSize         : Word;
    Handle             : THandle;
    VID                : DWord;
    PID                : DWord;
    VersionNumber      : Word;
    ManufacturerString : String;
    ProductString      : String;
    SerialNumberString : String;
end;

function GetVolumeNameForVolumeMountPointW(const lpszVolumeMountPoint: LPCWSTR;
  lpszVolumeName: LPWSTR; cchBufferLength: DWORD): BOOL; stdcall;
  external kernel32;

function HidD_GetAttributes(HidDeviceObject: THandle;
  var HidAttrs: THIDDAttributes): LongBool; stdcall;external 'hid.dll' name 'HidD_GetAttributes';
function HidD_GetManufacturerString(HidDeviceObject: THandle;
  Buffer: PWideChar; BufferLength: Integer): LongBool; stdcall;external 'hid.dll' name 'HidD_GetManufacturerString';
function HidD_GetProductString(HidDeviceObject: THandle;
  Buffer: PWideChar; BufferLength: Integer): LongBool; stdcall;external 'hid.dll' name 'HidD_GetProductString';
function HidD_GetSerialNumberString(HidDeviceObject: THandle;
  Buffer: PWideChar; BufferLength: Integer): LongBool; stdcall;external 'hid.dll' name 'HidD_GetSerialNumberString';

function GetVolumeName(Name: string): string;
var
  Volume: array [0..MAX_PATH] of Char;
begin
  FillChar(Volume[0], SizeOf(Volume), 0);
  GetVolumeNameForVolumeMountPointW(PChar(Name), @Volume[0], SizeOf(Volume));
  Result := Volume;
end;

Function GetHidDeviceInfo( Symlink : PChar) : THIDUSBDeviceInfo;
  Var
    pstr          : pWideChar;
    DevHandle    : THandle;
    HidAttrs     : THIDDAttributes;
  Begin
    FillChar(Result, SizeOf( Result), 0);
    Result.SymLink := SymLink+ #0;
    GetMem( pstr, 512);
    DevHandle := CreateFile( Symlink,
                             GENERIC_READ or GENERIC_WRITE,
                             FILE_SHARE_READ or FILE_SHARE_WRITE,
                             nil,
                             OPEN_EXISTING,
                             0,
                             0);
    If DevHandle <> INVALID_HANDLE_VALUE then
    begin
      If HidD_GetAttributes( DevHandle,HidAttrs) then
      begin
        result.VID           := HidAttrs.VendorID;
        result.PID           := HidAttrs.ProductID;
        result.VersionNumber := HidAttrs.VersionNumber;
      end;

      If HidD_GetManufacturerString( DevHandle, pstr, 512) then
        Result.ManufacturerString := pStr;

      If HidD_GetProductString( DevHandle, pstr, 512) then
        Result.ProductString := pStr;

      If HidD_GetSerialNumberString( DevHandle, pstr, 512) then
        Result.SerialNumberString := pStr;

      closeHandle( DevHandle);
    end;
    FreeMem( pStr);
  End;

procedure Main;
var
  VolumeName: string;
  info: THIDUSBDeviceInfo;
begin
  VolumeName:=GetVolumeName('i:\'); //assuming that I: is a USB drive
  info:=GetHidDeviceInfo(pchar(VolumeName));
  Writeln(info.SerialNumberString);
end;

begin
  Main;
  Readln;
end.

Upvotes: 0

Views: 6359

Answers (1)

You can try to obtain SerialNumber of disk (and more information) using WMI.

Usin WMI and the Win32_DiskDrive class, you can get the Serial Number. The documentation say: "Windows Server 2003 and Windows XP: This property is not available."

In Windows Vista,7/8 works fine.

To try if this method is good for you, try this simple demo on clubdelphi ftp(source included and binary included). In Windows 7 you get information like this:

enter image description here

If you can obtain a correct serial, you can use WMI.

Good library for work with WMI is GLibWMI on Sourceforge. Include a specific component (DiskDriveInfo) that you can use with 0 code lines. See demo.

enter image description here

Regards

Upvotes: 1

Related Questions