delphi – 如何查找闪存设备的唯一序列号?

我找到了几个片段和.pas文件,可以检测何时插入和移除USB闪存驱动器.有些提供了所有类型的好信息,但我需要的是设备的唯一序列号,而不是卷的序列号.

我当前的.pas文件(我不记得我发现的地方)似乎也检测到SD卡(我喜欢).如果你想要一个外观,你可以在这里找到它(它只返回驱动器号并插入/删除):

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,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,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调用“where index = found_index”结合起来.

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

解决方法

您可以在 Magenta Systems之前使用WMI库,这可以消除使用WMI查询的大部分痛苦.免费下载包括代码和示例项目,允许您使用API​​并查询您的内容.您将需要保留一个官方Microsoft API documentation链接,它将帮助您执行哪些查询获取哪些信息…您有兴趣使用sql语法查询查询类.

例如,执行查询

SELECT * FROM Win32_diskDrive Where InterfaceType = 'USB'

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

编辑检查我唯一方便的USB设备返回了硬件序列号“u”,但是看起来很长且有效的PNPdeviceid似乎包含序列号,这就是我建议该字段的原因.

编辑您可以通过对Win32_Logicaldisk执行查询获取驱动器号,您还可以查询Win32_diskDrivetodiskPartition,其中包含Win32_diskDrive和Win32_diskPartition之间的映射.最后,Win32_LogicaldiskToPartition然后将逻辑磁盘映射到分区,从而使您能够将物理USB驱动器链接到特定的驱动器号.

相关文章

 从网上看到《Delphi API HOOK完全说明》这篇文章,基本上都...
  从网上看到《Delphi API HOOK完全说明》这篇文章,基本上...
ffmpeg 是一套强大的开源的多媒体库 一般都是用 c/c+&#x...
32位CPU所含有的寄存器有:4个数据寄存器(EAX、EBX、ECX和ED...
1 mov dst, src dst是目的操作数,src是源操作数,指令实现的...