Delphi-Comment obtenir la liste des disques durs amovibles USB et des clés USB?

dans mon application (Delphi), je dois lister tous les périphériques de stockage USB. Ceux-ci peuvent être soit Flash Memory sticks ou disques de stockage externes.

il y a un Jvcl composant JvDriveCombo, et il a l' DriveType propriété - le problème est que je sélectionne DriveType := Fixed ensuite, en plus du lecteur externe, il Liste également les lecteurs internes (C:,D: etc). Cependant, je ne veux lister que les disques externes.

je crois qu'il en est DeviceIoControl function (Je l'ai vu sur MSDN) mais je n'ai aucune idée de comment l'utiliser.

je me demande si quelqu'un peut m'aider avec la bonne façon / code pour lister les périphériques de stockage USB?

Merci.

EDIT:

je viens de trouver un exemple de code et je suis le poster ici:

uses .... jwawinbase, JwaWinIoctl;

procedure TForm1.Button1Click(Sender: TObject);
var
  DriveCmdStr: string;
  DriveHandle: THandle;
  ADriveLetter: string;
  hp: STORAGE_HOTPLUG_INFO;
  rlen: DWORD;
begin

  ADriveLetter := 'H';
  DriveCmdStr := Format('.%s:', [ADriveLetter]);
  DriveHandle := CreateFile(PChar(DriveCmdStr), GENERIC_READ, FILE_SHARE_WRITE,
    nil, OPEN_EXISTING, 0, 0);

  if DriveHandle = INVALID_HANDLE_VALUE then
    Exit;

  DeviceIoControl(DriveHandle, IOCTL_STORAGE_GET_HOTPLUG_INFO, nil, 0, @hp,
    SizeOf(hp), @rlen, nil);

  CloseHandle(DriveHandle);

  if hp.MediaRemovable then
    showmessage('media removable');

end;

Maintenant j'aimerais juste savoir comment énumérer toutes les lettres de lecteur. Qui est le plus efficace?

14
demandé sur Saidolim 2010-09-15 17:42:00

3 réponses

{$MINENUMSIZE 4}
const
  IOCTL_STORAGE_QUERY_PROPERTY =  2D1400;

type
  STORAGE_QUERY_TYPE = (PropertyStandardQuery = 0, PropertyExistsQuery, PropertyMaskQuery, PropertyQueryMaxDefined);
  TStorageQueryType = STORAGE_QUERY_TYPE;

  STORAGE_PROPERTY_ID = (StorageDeviceProperty = 0, StorageAdapterProperty);
  TStoragePropertyID = STORAGE_PROPERTY_ID;

  STORAGE_PROPERTY_QUERY = packed record
    PropertyId: STORAGE_PROPERTY_ID;
    QueryType: STORAGE_QUERY_TYPE;
    AdditionalParameters: array [0..9] of AnsiChar;
  end;
  TStoragePropertyQuery = STORAGE_PROPERTY_QUERY;

  STORAGE_BUS_TYPE = (BusTypeUnknown = 0, BusTypeScsi, BusTypeAtapi, BusTypeAta, BusType1394, BusTypeSsa, BusTypeFibre,
    BusTypeUsb, BusTypeRAID, BusTypeiScsi, BusTypeSas, BusTypeSata, BusTypeMaxReserved = F);
  TStorageBusType = STORAGE_BUS_TYPE;

  STORAGE_DEVICE_DESCRIPTOR = packed record
    Version: DWORD;
    Size: DWORD;
    DeviceType: Byte;
    DeviceTypeModifier: Byte;
    RemovableMedia: Boolean;
    CommandQueueing: Boolean;
    VendorIdOffset: DWORD;
    ProductIdOffset: DWORD;
    ProductRevisionOffset: DWORD;
    SerialNumberOffset: DWORD;
    BusType: STORAGE_BUS_TYPE;
    RawPropertiesLength: DWORD;
    RawDeviceProperties: array [0..0] of AnsiChar;
  end;
  TStorageDeviceDescriptor = STORAGE_DEVICE_DESCRIPTOR;

function GetBusType(Drive: AnsiChar): TStorageBusType;
var
  H: THandle;
  Query: TStoragePropertyQuery;
  dwBytesReturned: DWORD;
  Buffer: array [0..1023] of Byte;
  sdd: TStorageDeviceDescriptor absolute Buffer;
  OldMode: UINT;
begin
  Result := BusTypeUnknown;

  OldMode := SetErrorMode(SEM_FAILCRITICALERRORS);
  try
    H := CreateFile(PChar(Format('\.\%s:', [AnsiLowerCase(Drive)])), 0, FILE_SHARE_READ or FILE_SHARE_WRITE, nil,
      OPEN_EXISTING, 0, 0);
    if H <> INVALID_HANDLE_VALUE then
    begin
      try
        dwBytesReturned := 0;
        FillChar(Query, SizeOf(Query), 0);
        FillChar(Buffer, SizeOf(Buffer), 0);
        sdd.Size := SizeOf(Buffer);
        Query.PropertyId := StorageDeviceProperty;
        Query.QueryType := PropertyStandardQuery;
        if DeviceIoControl(H, IOCTL_STORAGE_QUERY_PROPERTY, @Query, SizeOf(Query), @Buffer, SizeOf(Buffer), dwBytesReturned, nil) then
          Result := sdd.BusType;
      finally
        CloseHandle(H);
      end;
    end;
  finally
    SetErrorMode(OldMode);
  end;
end;


procedure GetUsbDrives(List: TStrings);
var
  DriveBits: set of 0..25;
  I: Integer;
  Drive: AnsiChar;
begin
  List.BeginUpdate;
  try
    Cardinal(DriveBits) := GetLogicalDrives;

    for I := 0 to 25 do
      if I in DriveBits then
      begin
        Drive := Chr(Ord('a') + I);
        if GetBusType(Drive) = BusTypeUsb then
          List.Add(Drive);
      end;
  finally
    List.EndUpdate;
  end;
end;
13
répondu Ondrej Kelle 2010-09-15 14:44:48

vous pouvez accéder à ces informations en utilisant WMI. Si vous utilisez ce SQL, vous pouvez accéder aux informations sur les disques installés.

select * from Win32_diskdrive where size<>NULL

ce code récupère des informations sur les disques durs.

procedure  TForm1.DoInventario(aWSQL:string; var mmResult:TMemo);
var
  Locator:ISWbemLocator;
  Services:ISWbemServices;
  SObject:ISWbemObject;
  ObjSet:ISWbemObjectSet;
  Enum:IEnumVariant;
  TempObj:OleVariant;
  Value:Cardinal;
  TS:TStrings;
begin

  try
    Locator := CoSWbemLocator.Create();
    // Conectar con el Servicio de WMI
    Services := Locator.ConnectServer(
        STR_LOCALHOST,        {ordenador local}
        STR_CIM2_ROOT,        {root}
        STR_EMPTY, STR_EMPTY, {usuario y password -en local no son necesarios-}
        STR_EMPTY,STR_EMPTY, 0, nil);
    // Acceder a los datos
    ObjSet := Services.ExecQuery(aWSQL, 'WQL',
                wbemFlagReturnImmediately and wbemFlagForwardOnly , nil);
    Enum :=  (ObjSet._NewEnum) as IEnumVariant;
    // Hemos encontrado algun objeto?
    while (Enum.Next(1, TempObj, Value) = S_OK) do begin
      SObject := IUnknown(TempObj) as ISWBemObject;
      // encontrado?
      if (SObject <> nil) then begin
        // Acceder a la propiedad
        SObject.Properties_;
        // Cargamos las propiedades
        TS := TStringList.Create();
        try
          TS.Add(SObject.GetObjectText_(0));
          // lo pasamos al memo
          mmResult.Lines.Text := mmResult.Lines.Text + TS.Text;
        finally
          FreeAndNil(TS);
        end;
      end;
    end;
  except
    // Recuperar excepciones
  end;

end;

vous devez ajouter ActiveX et WbemScripting_TLB (cela doit être importé) dans vos utilisations. Avec cela, vous pouvez accéder à toutes les informations des disques.

pour récupérer la lettre de tous les disques que vous pouvez combiner (récupérer peut faire avec le même code) l'accès aux classes Win32_LogicalDiskToPartition et Win32_DiskDrive.

select * from Win32_LogicalDiskToPartition
select * from Win32_DiskDrive

si vous recherchez WMI, vous pouvez trouver d'autres codes apparentés.

Cordialement.

4
répondu Germán Estévez -Neftalí- 2010-09-15 15:16:47

Je ne suis pas sûr si vous cherchez juste à énumérer des lettres de lecteur? La boucle en boucle ci-dessous fait ça, en parcourant toutes les lettres, qu'il y ait ou non un lecteur pour cette lettre.

Ou, si vous êtes à la recherche pour une autre façon de trouver des lecteurs amovibles, il existe une fonction pour que ci-dessous, trop. (La vôtre peut-être mieux...) Étonnamment, sur mon test, Windows.GetDriveType ne considère pas les lecteurs de CD comme amovibles. Les lecteurs USB sont marqués comme amovible, comme on le ferait attendre.

  Function RemovableDrive(Drive: char): Boolean;
  begin
    Result := (Windows.GetDriveType(PChar(Drive + ':\')) = Windows.Drive_Removable);
  end;

  procedure TForm1.Button1Click(Sender: TObject);
  var
    Drive: Char;
  begin
    for Drive := 'A' to 'Z' do
      Memo1.Lines.Add('Drive: ' + Drive + ' is ' + BoolToStr(RemovableDrive(Drive), TRUE));
  end;
3
répondu RobertFrank 2010-09-15 14:42:12