2010-11-27 36 views
3

デルファイでUSBフラッシュドライブの製造元シリアル番号を取得するにはどうすればよいですか?USBフラッシュドライブの製造元のシリアル番号を取得するにはどうすればよいですか?

function GetDiskVolSerialID(ADriveName: Char): Cardinal; 
var 
    DiskDrive: string; 
    FileSystemFlags: DWORD; 
    VolumeSerialNumber: DWORD; 
    MaximumComponentLength: DWORD; 
begin 
    DiskDrive := ADriveName + ':\'; 
    GetVolumeInformation(PChar(DiskDrive), 
         nil, 
         0, 
         @VolumeSerialNumber, 
         MaximumComponentLength, 
         FileSystemFlags, 
         nil, 
         0); 
    Result := VolumeSerialNumber; 
end; 

をしかし、それは正しい結果を返しません:

私はこれを試してみました!

+0

ハードディスクがフォーマットされている場合、または製造元のシリアル番号がWindowsで割り当てられるシリアル番号を入力しますか? – RRUZ

+0

メーカーのシリアル番号! – opc0de

+3

WMIは、ハードウェアを含む情報システムへのアクセスを容易にするために作成されました.WMIは、この種のタスクのための完璧なツールです。私はWMIを使わないようにするあなたのモチベーションは何か分かりません。あなたはそれを説明できますか? – RRUZ

答えて

12

opc0de、コメントに応じて私はあなたにWMIを使用したサンプルを提供します。

最初に、投稿したコード(GetVolumeInformation関数を使用)は、ディスクをフォーマットするときにwindowsによって割り当てられたシリアル番号を返します。 2つのWMIクラスが存在しWICH

良いニュースですが、これらのクラスはWin32_DiskDriveWin32_PhysicalMediaあるthe Number allocated by the manufacturer to identify the physical media.を保存SerialNumberと呼ばれるプロパティを公開します。

残念ながら、このクラスは論理ディスクの文字(C、D、E、F ...)と直接関連付けられていません。なぜなら、別のwmiクラスを呼び出して論理ドライブ文字と物理ドライブ。

このシリアル番号を取得するには、先にこのリンクを見つける必要があります。この関連を見つけるためのシーケンスは、これと同じです。

Win32_DiskPartition - >Win32_LogicalDiskToPartition - >Win32_DiskDrive

これはWin32_DiskDriveクラスを使用して、USBのシリアル番号を取得するためのコードです。いくつかの時間前、私は、WMIを使用して、システム情報にアクセスするためのDelphiコードを生成するためにあなたを助けることができるWMI Delphi Code Creatorと呼ばれるアプリケーションを書いところで

program GetWMI_Info; 

{$APPTYPE CONSOLE} 

uses 
    SysUtils, 
    StrUtils, 
    ActiveX, 
    ComObj, 
    Variants; 

function VarArrayToStr(const vArray: variant): string; 

    function _VarToStr(const V: variant): string; 
    var 
    Vt: integer; 
    begin 
    Vt := VarType(V); 
     case Vt of 
      varSmallint, 
      varInteger : Result := IntToStr(integer(V)); 
      varSingle, 
      varDouble, 
      varCurrency : Result := FloatToStr(Double(V)); 
      varDate  : Result := VarToStr(V); 
      varOleStr : Result := WideString(V); 
      varBoolean : Result := VarToStr(V); 
      varVariant : Result := VarToStr(Variant(V)); 
      varByte  : Result := char(byte(V)); 
      varString : Result := String(V); 
      varArray : Result := VarArrayToStr(Variant(V)); 
     end; 
    end; 

var 
i : integer; 
begin 
    Result := '['; 
    if (VarType(vArray) and VarArray)=0 then 
     Result := _VarToStr(vArray) 
    else 
    for i := VarArrayLowBound(vArray, 1) to VarArrayHighBound(vArray, 1) do 
    if i=VarArrayLowBound(vArray, 1) then 
     Result := Result+_VarToStr(vArray[i]) 
    else 
     Result := Result+'|'+_VarToStr(vArray[i]); 

    Result:=Result+']'; 
end; 

function VarStrNull(const V:OleVariant):string; //avoid problems with null strings 
begin 
    Result:=''; 
    if not VarIsNull(V) then 
    begin 
    if VarIsArray(V) then 
     Result:=VarArrayToStr(V) 
    else 
    Result:=VarToStr(V); 
    end; 
end; 


function GetWMIObject(const objectName: String): IDispatch; //create the Wmi instance 
var 
    chEaten: Integer; 
    BindCtx: IBindCtx; 
    Moniker: IMoniker; 
begin 
    OleCheck(CreateBindCtx(0, bindCtx)); 
    OleCheck(MkParseDisplayName(BindCtx, StringToOleStr(objectName), chEaten, Moniker)); 
    OleCheck(Moniker.BindToObject(BindCtx, nil, IDispatch, Result)); 
end; 



function GetUsbDriveSerial(const Drive:AnsiChar):string; 
var 
    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:=''; 
    objWMIService := GetWMIObject('winmgmts:\\localhost\root\CIMV2'); //Connect to the WMI 
    //colDiskDrives := objWMIService.ExecQuery('SELECT DeviceID,SerialNumber FROM Win32_DiskDrive WHERE InterfaceType="USB"','WQL',0); 
    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 
       if VarStrNull(objLogicalDisk.DeviceID)=(Drive+':') then //compare the device id 
       begin 
        Result:=VarStrNull(objDiskDrive.SerialNumber); 
        Exit; 
       end; 
     end; 
    end; 
end; 

begin 
try 
    CoInitialize(nil); 
    try 
     Writeln(GetUsbDriveSerial('F')); 
     Readln; 
    finally 
     CoUninitialize; 
    end; 
except 
    on E:Exception do 
    begin 
     Writeln(E.Classname, ':', E.Message); 
     Readln; 
    end; 
    end; 
end. 

。あなたはPnPDeviceIDプロパティからシリアル番号を抽出することができ、この例のように、USBディスクの

UPDATE

一部のドライバは、Win32_DiskDrive.SerialNumberプロパティのメーカーのシリアル番号を公開していません。

このサンプルコードを確認してください。

{$APPTYPE CONSOLE} 

uses 
    SysUtils, 
    StrUtils, 
    ActiveX, 
    ComObj, 
    Variants; 


function VarStrNull(const V:OleVariant):string; //avoid issues with null variants 
begin 
    Result:=''; 
    if not VarIsNull(V) then 
    Result:=VarToStr(V); 
end; 


function GetUsbDriveSerial(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; 
       objLogicalDisk:=Unassigned; 
       Exit; 
      end; 
      objLogicalDisk:=Unassigned; 
      end; 
      objPartition:=Unassigned; 
     end; 
     objDiskDrive:=Unassigned; 
    end; 
end; 

begin 
try 
    CoInitialize(nil); 
    try 
     Writeln(GetUsbDriveSerial('F')); 
     Readln; 
    finally 
     CoUninitialize; 
    end; 
except 
    on E:Exception do 
    begin 
     Writeln(E.Classname, ':', E.Message); 
     Readln; 
    end; 
    end; 
end. 
+0

コードを実行しているときに、次の例外が発生しました。無効なクエリany ideaaなぜですか? – opc0de

+2

OK、これはWMIのバージョンがこの行を変更したためです。 'colDiskDrives:= objWMIService.ExecQuery( 'Win32_DiskDrive FROM Win32_DiskDrive WHERE InterfaceType =" USB "、' WQL '、0); 'to' colDiskDrives:= objWMIService.ExecQuery( 'SELECT * FROM Win32_DiskDrive WHERE InterfaceType = "USB"'、 'WQL'、0); ' – RRUZ

+0

コードはWMIの古いバージョンと互換性があるように編集されました。 – RRUZ

2

コンポーネントTDiskInfo from GLibを試すと、SerialNumberを取得できます。
WMIは使用しませんが、一部のシステム(ディスクタイプ)では番号を取得しません。
お試しください。それは無料です。

よろしくお願いいたします。

関連する問題