如何获得USB记忆棒驱动器的驱动器号给定其卷标?

时间:2014-10-10 16:04:54

标签: windows delphi delphi-xe2

USB记忆棒有两个分区 - 一个只读,另一个读写。

我的程序从只读分区运行。

两个分区的卷标由制造商确定: MYDISK-RO和MYDISK-RW

在Windows中插入时,每个分区(卷)都会获得不同的驱动器号。根据配置,这些驱动器号在不同的计算机上是不同的。已分配给磁盘驱动器的驱动器号的数量。

我的问题是:

使用卷标找到程序找到读写分区的驱动器号的最佳(最有效)方法是什么?

它需要在Windows XP及更高版本上运行。

我没有枚举所有的驱动器号并将卷标与我们需要的卷标进行比较,而是理想地寻找对Windows的单个函数调用。例如:

GetDriveLetterByVolumeName(AVolumeLabel:String);

GetVolumeInformation(AVolumeLabel:String);

是否有这样的功能或枚举驱动器号并将每个卷标比较唯一的解决方案?

TIA。

2 个答案:

答案 0 :(得分:1)

很久以前我用过这段代码(在Delphi7上) 此过程在组合框中添加所有可移动驱动器的所有根

Procedure TfMain.GetDiskDrives();
var
  r: LongWord;
  Drives: array[0..128] of char;
  pDrive: pchar;
begin
  Result := '';
  r := GetLogicalDriveStrings(sizeof(Drives), Drives);
  if r = 0 then exit;
  if r > sizeof(Drives) then
    raise Exception.Create(SysErrorMessage(ERROR_OUTOFMEMORY));
  pDrive := Drives;  // Point to the first drive
  while pDrive^ <> #0 do begin
    if GetDriveType(pDrive) = DRIVE_REMOVABLE then begin
       cDrive.Items.Add(pDrive);
    end;
    inc(pDrive, 4);  // Point to the next drive
  end;
  if cDrive.Items.Count=1 then cDrive.ItemIndex:=0;
end;

之后,您可以使用以下函数获取卷名

function GetVolumeName(DriveLetter: Char): string;
var
  dummy: DWORD;
  buffer: array[0..MAX_PATH] of Char;
  oldmode: LongInt;
begin
  oldmode := SetErrorMode(SEM_FAILCRITICALERRORS);
  try
    GetVolumeInformation(PChar(DriveLetter + ':\'),
                         buffer,
                         SizeOf(buffer),
                         nil,
                         dummy,
                         dummy,
                         nil,
                         0);
    Result := StrPas(buffer);
  finally
    SetErrorMode(oldmode);
  end;
end;

答案 1 :(得分:-1)

我发布的代码改编自Gianluca Colombo的答案:

在Windows 7 x64上测试并使用Delphi XE2 Update 4.1。

unit uDiskUtils;

interface

uses Windows, Classes, SysUtils;

Procedure GetDiskDrives(var ADriveList: TStrings);
function GetVolumeName(const ADriveLetter: Char): string;
function FindDiskDriveByVolumeName(const AVolumeName: String): Char;

implementation

Procedure GetDiskDrives(var ADriveList: TStrings);
var
  r: LongWord;
  Drives: array [0 .. 128] of Char;
  pDrive: pchar;
begin

  ADriveList.Clear;

  r := GetLogicalDriveStrings(sizeof(Drives), Drives);
  if r = 0 then
    exit;
  if r > sizeof(Drives) then
    raise Exception.Create(SysErrorMessage(ERROR_OUTOFMEMORY));
  pDrive := Drives; // Point to the first drive
  while pDrive^ <> #0 do
  begin
    if GetDriveType(pDrive) = DRIVE_REMOVABLE then
    begin
      ADriveList.Add(pDrive);
    end;
    inc(pDrive, 4); // Point to the next drive
  end;
end;

function GetVolumeName(const ADriveLetter: Char): string;
var
  dummy: DWORD;
  buffer: array [0 .. MAX_PATH] of Char;
  oldmode: LongInt;
begin
  oldmode := SetErrorMode(SEM_FAILCRITICALERRORS);
  try
    GetVolumeInformation(pchar(ADriveLetter + ':\'), buffer, sizeof(buffer), nil, dummy, dummy, nil, 0);
    Result := StrPas(buffer);
  finally
    SetErrorMode(oldmode);
  end;
end;

function FindDiskDriveByVolumeName(const AVolumeName: String): Char;
var
  dl: TStringList;
  c: Integer;
begin
  Result := ' ';

  dl := TStringList.Create;
  try
    GetDiskDrives(TStrings(dl));

    for c := 0 to dl.Count - 1 do
      if (AVolumeName = GetVolumeName(dl[c][1])) then
        Result := dl[c][1];

  finally
    dl.Free;
  end;

end;

end.