Delphi - كيفية الحصول على قائمة بمحركات الأقراص الصلبة القابلة للإزالة USB وعصي الذاكرة؟

StackOverflow https://stackoverflow.com/questions/3718192

سؤال

في طلبي (Delphi) ، أحتاج إلى سرد جميع أجهزة تخزين USB. يمكن أن تكون هذه إما عصي ذاكرة فلاش أو محركات التخزين الخارجية.

هناك Jvcl مكون JvDriveCombo, ولديه DriveType الخاصية - المشكلة هي إذا اخترت DriveType := Fixed ثم بالإضافة إلى محرك الأقراص الخارجي ، يسرد أيضًا محركات الأقراص الداخلية (C:\, D:\ إلخ). ومع ذلك ، أريد فقط سرد محركات الأقراص الخارجية.

أعتقد أن هناك وظيفة iviceiocontrol (رأيتها على MSDN) ولكن ليس لدي أي فكرة عن كيفية استخدامها.

أتساءل عما إذا كان يمكن لأي شخص مساعدتي في الطريق / الكود المناسب لسرد أجهزة تخزين USB؟

شكرًا.

تعديل:

لقد وجدت للتو بعض رمز النماذج وأقوم بنشره هنا:

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;

الآن أود فقط أن أعرف كيفية تعداد جميع رسائل القيادة. ما هي الوظيفة الأكثر كفاءة؟

هل كانت مفيدة؟

المحلول

{$MINENUMSIZE 4}
const
  IOCTL_STORAGE_QUERY_PROPERTY =  $002D1400;

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 = $7F);
  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;

نصائح أخرى

يمكنك الوصول إلى هذه المعلومات باستخدام WMI. إذا كنت تستخدم SQL هذا ، فيمكنك الوصول إلى معلومات حول الأقراص المثبتة.

select * from Win32_diskdrive where size<>NULL

هذا الرمز يحسب المعلومات حول محركات الأقراص.

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;

يجب عليك إضافة ActiveX و WBEmscripting_tlb (يجب استيراد هذا) في استخداماتك. مع هذا ، يمكنك الوصول إلى جميع معلومات الأقراص.

لإعادة محاكمة الحرف من جميع القرص الذي يمكنك دمجه (يمكن أن تفعل الاسترداد مع نفس الرمز) الوصول إلى الفئات win32_logicalDiskTopartition و Win32_DiskDrive.

select * from Win32_LogicalDiskToPartition
select * from Win32_DiskDrive

إذا قمت بالبحث في WMI ، يمكنك العثور على المزيد من الرموز ذات الصلة.

يعتبر.

لست متأكدًا مما إذا كنت تتطلع فقط إلى تعداد رسائل القيادة؟ يقوم الحلقة أدناه بذلك ، حيث يمر بجميع الرسائل ، بغض النظر عما إذا كان هناك محرك لهذه الرسالة.

أو ، إذا كنت تبحث عن طريقة مختلفة للعثور على محركات أقراص قابلة للإزالة ، فهناك وظيفة لذلك أدناه أيضًا. (قد يكون لك أفضل ...) من المستغرب ، في الاختبار الخاص بي ، لا تعتبر windows.getDrivetype محركات الأقراص المضغوطة قابلة للإزالة. يتم وضع علامة على محركات أقراص USB على أنها قابلة للإزالة ، كما يتوقع المرء.

  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;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top