如何找到闪存设备的唯一序列号? [英] How to find the unique serial number of a flash device?

查看:306
本文介绍了如何找到闪存设备的唯一序列号?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现了几个片段和.pas文件,可以检测USB闪存驱动器的插入和删除。有些提供各种好的信息,但是我需要的是设备的唯一序列号,而不是卷的序列号。

I've found several snippets and .pas files that can detect when USB flash drives are inserted and removed. Some give all kind of good information, however what I need is the devices' unique serial number, not the volumes' serial number.

我目前的.pas文件不记得我发现了什么)也似乎检测到SD卡(我喜欢)。如果你想看看,你可以在这里找到它(它只返回驱动器号码并插入/删除):

My current .pas file (which I don't remember where I found) also seems to detect SD cards (which I like). If you want a look, you can find it here (it only returns the drive number and inserted/removed):

unit UsbDetector;

interface

uses Classes;

type
  TUsbDriveChanged = procedure (Sender: TObject; Drive: string; Attached: boolean) of object;

procedure StartUsbDetector(NotifyProc: TUsbDriveChanged);
procedure StopUsbDetector;

implementation

uses Windows, Messages, Forms, SysUtils;

type
  TUSBDetector = class(TObject)
  private
    fUsbDriveChanged: TUsbDriveChanged;
  protected
    procedure DeviceChanged(Msg: UINT; wParam, lParam: Longint);
    procedure DoUsbDriveChanged(Drive: string; Attached: Boolean); dynamic;
  public
    constructor Create(NotifyProc: TUsbDriveChanged);
    destructor Destroy; override;
    property OnUsbDriveChanged: TUsbDriveChanged read fUsbDriveChanged;
  end;

var mUSBDetector: TUSBDetector;

procedure StartUsbDetector(NotifyProc: TUsbDriveChanged);
begin
  if not Assigned(mUsbDetector) then
    mUsbDetector := TUsbDetector.Create(NotifyProc);
end;

procedure StopUsbDetector;
begin
  FreeAndNil(mUsbDetector);
end;

{----------------------------------------------------------------------------}
// Device constants
const
  DBT_DEVICEARRIVAL          =  $00008000;
  DBT_DEVICEREMOVECOMPLETE   =  $00008004;
  DBT_DEVTYP_VOLUME          =  $00000002;

// Device structs
type
  _DEV_BROADCAST_HDR         =  packed record
     dbch_size:              DWORD;
     dbch_devicetype:        DWORD;
     dbch_reserved:          DWORD;
  end;
  DEV_BROADCAST_HDR          =  _DEV_BROADCAST_HDR;
  TDevBroadcastHeader        =  DEV_BROADCAST_HDR;
  PDevBroadcastHeader        =  ^TDevBroadcastHeader;

type
  _DEV_BROADCAST_VOLUME      =  packed record
     dbch_size:              DWORD;
     dbch_devicetype:        DWORD;
     dbch_reserved:          DWORD;
     dbcv_unitmask:          DWORD;
     dbcv_flags:             WORD;
  end;
  DEV_BROADCAST_VOLUME       =  _DEV_BROADCAST_VOLUME;
  TDevBroadcastVolume        =  DEV_BROADCAST_VOLUME;
  PDevBroadcastVolume        =  ^TDevBroadcastVolume;

var
  fPrevWndProc: TFNWndProc = nil;

function UsbWndProc(hWnd: HWND; Msg: UINT; wParam, lParam: Longint): Longint; stdcall;
begin
  Result := CallWindowProc(fPrevWndProc, hWnd, Msg, wParam, lParam);
  if (Msg = WM_DEVICECHANGE) and (mUsbDetector <> nil) then
    mUsbDetector.DeviceChanged(Msg, wParam, lParam);
end;

constructor TUSBDetector.Create(NotifyProc: TUsbDriveChanged);
begin
  inherited Create;
  fUsbDriveChanged := NotifyProc;
  if not Assigned(fPrevWndProc) then 
  begin
    fPrevWndProc := TFNWndProc(GetWindowLong(Application.Handle, GWL_WNDPROC));
    SetWindowLong(Application.Handle, GWL_WNDPROC, LongInt(@UsbWndProc));
  end;
end;

destructor TUSBDetector.Destroy;
begin
  //SetWindowLong(Application.Handle, GWL_WNDPROC, LongInt(@fPrevWndProc));
  inherited Destroy;
end;

procedure TUSBDetector.DeviceChanged(Msg: UINT; wParam, lParam: LongInt);
var
  lpdbhHeader: PDevBroadcastHeader;
  lpdbvData: PDevBroadcastVolume;
  dwIndex: Integer;
  lpszDrive: string;
begin
  // Get the device notification header
  lpdbhHeader := PDevBroadcastHeader(lParam);
  // Handle the message
  lpszDrive := '';
  case WParam of
    DBT_DEVICEARRIVAL:    {a USB drive was connected}
    begin
      if lpdbhHeader^.dbch_devicetype = DBT_DEVTYP_VOLUME then
      begin
        lpdbvData := PDevBroadcastVolume(lParam);
        for dwIndex := 0 to 25 do
        begin
          if (lpdbvData^.dbcv_unitmask shr dwIndex) = 1 then
          begin
            lpszDrive := lpszDrive + Chr(65 + dwIndex) + ':\';
            break;
          end;
        end;
        DoUsbDriveChanged(lpszDrive, True);
      end;
    end;
    DBT_DEVICEREMOVECOMPLETE:    {a USB drive was removed}
    begin
      if lpdbhHeader^.dbch_devicetype = DBT_DEVTYP_VOLUME then
      begin
        lpdbvData := PDevBroadcastVolume(lParam);
        for dwIndex := 0 to 25 do
        begin
          if (lpdbvData^.dbcv_unitmask shr dwIndex) = 1 then
          begin
            lpszDrive := lpszDrive + Chr(65 + dwIndex) + ':\';
            break;
          end;
        end;
        DoUsbDriveChanged(lpszDrive, False);
      end;
    end;
  end;
end;

procedure TUSBDetector.DoUsbDriveChanged(Drive: string; Attached: Boolean);
begin
  if Assigned(fUsbDriveChanged) then
    fUsbDriveChanged(Self, Drive, Attached);
end;

end.

代码亮点失败。

总之;
当插入/移除可移动存储器时,获取驱动器盘符及其唯一的序列号。可能将已经给出的代码与WMI调用其中Index = found_index组合。

All in all; When a removable is inserted/removed, get drive letter and its unique serial number. Maybe combine the already given code with a WMI call "where Index=found_index".

****编辑!****
我删除了其中RRUZ给出的代码。我终于找到了如何处理数组,所以我用它来找到Capabilities [i] = 7来获取所有可移动媒体。现在我只需要将这段代码与上面的代码连接起来。我正在考虑使用Index,但是我不知道如何使用GetDrive MapInfo。如果你能提供一个获取驱动器号的例子,我的问题就解决了。

****EDIT!**** I removed the "where" clause in the code given by RRUZ. I finally found out how to handle the arrays, so I use that to find Capabilities[i]=7 to get all removable media. Now I just need to connect this code with the above code. I am thinking using Index, but I don't know how to use GetDrive MapInfo. If you could provide me with an example on getting the drive letter, my question is solved.

推荐答案

你可以使用WMI库通过 Magenta Systems ,它占用了大部分使用WMI查询的痛苦。免费下载包括源代码和示例项目,可让您使用API​​和查询您的内容。您将需要链接到官方Microsoft API文档的链接,这将帮助您执行什么查询以获取什么信息...您有兴趣使用SQL查询类语法查询。

You can use the WMI library by Magenta Systems which takes most of the pain of using WMI queries. The free download includes source and an example project that allows you to play with the API and queries to your hearts content. You will want to keep a link to the official Microsoft API documentation which will help you with what query to execute to get what information...your interested in querying the classes using SQL like syntax queries.

例如,执行查询

SELECT * FROM Win32_DiskDrive Where InterfaceType = 'USB'

返回有关当前连接到机器的所有USB设备的大量信息。您可以使用PNPDeviceID作为唯一的标识符。

returns a wealth of information about all of the USB devices currently connected to the machine. You can then use the PNPDeviceID as a unique identifier.

编辑检查唯一的USB设备我方便地返回了一个硬件序列号u 但是一个非常长的有效期望的PNPDeviceID,似乎包含一个序列号,这就是为什么我建议该字段。

EDIT checking the only USB device I had handy returned a hardware serial number of "u" but a very long and valid looking PNPDeviceID which appeared to include a serial number, which is why I suggested that field.

编辑你可以通过对 Win32_LogicalDisk 执行查询获取驱动器号,您还可以查询 Win32_DiskDriveToDiskPartition ,其中包含 Win32_DiskDrive Win32_DiskPartition 。最后, Win32_LogicalDiskToPartition 然后将逻辑磁盘映射到分区,从而使您能够将物理USB驱动器链接到特定的驱动器号。

EDIT You can get the drive letter by performing a query against Win32_LogicalDisk you can also query Win32_DiskDriveToDiskPartition which contains a mapping between Win32_DiskDrive and Win32_DiskPartition. Finally Win32_LogicalDiskToPartition then maps a logical disk to a partition which in turn gives you the ability to link a physical USB drive to a specific drive letter.

这篇关于如何找到闪存设备的唯一序列号?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆