我想映射Windows中所有驱动器的所有分区(未映射的驱动器)。我的意思是我想给每个人分配驱动器号。 我知道您可以使用FindFirstVolume,FindNextVolume,FindVolumeClose来执行此操作,但有些情况下您无法使用它们。 我尝试使用QueryDosDevice,同样的事情。
这个想法是从\。\ PhysicalDrive [n]开始,找出分区并映射它们。 我知道这是可行的,因为我看到了一个可以做到这一点的程序。但我不喜欢它,因为它也映射了隐藏的分区。
有人知道某种方式......? 谢谢。
答案 0 :(得分:3)
我做到了:) 我创建了一个程序,在程序启动时添加或删除驱动器号 - 如果在计算机中添加或删除了一个或多个存储驱动器:
program MapDrives;
uses Windows;
type
TPARTITION_INFORMATION = record
StartingOffset: _LARGE_INTEGER; //TLargeInteger;
PartitionLength: _LARGE_INTEGER; //TLargeInteger;
HiddenSectors: DWORD;
PartitionNumber: DWORD;
PartitionType: BYTE;
BootIndicator: BOOLEAN;
RecognizedPartition: BOOLEAN;
RewritePartition: BOOLEAN;
end;
function IntToStr(Value: Integer): string;
begin
if Value < 10 then
Result := Char(Value + 48)
else
Result := Char(Value div 10 + 48) + Char(Value + 48);
end;
function GetNextAvailableLetter: AnsiChar;
var Drives, mask: DWord;
i: Integer;
begin
Drives := GetLogicalDrives;
mask := 4;
Result := 'Z';
for i := 3 to 26 do //C to Z
begin
if mask and Drives = 0 then
begin
Result := AnsiChar(64 + i);
Exit;
end;
mask := mask shl 1;
end;
end;
const IOCTL_DISK_GET_PARTITION_INFO = $0074004;
var i, j, k: Integer;
H: THandle;
dwBytesReturned: DWORD;
BreakCycle, DoMount: Boolean;
NextLetter: AnsiChar;
PartitionInformation: TPARTITION_INFORMATION;
PartitionsInformation: array of TPARTITION_INFORMATION;
Drives, mask: DWord;
OldMode: UINT;
begin
OldMode := SetErrorMode(SEM_FAILCRITICALERRORS); //so it shouldn't ask to insert CD or card
//gets informations about already mounted partitions
SetLength(PartitionsInformation, 0);
Drives := GetLogicalDrives;
mask := 4;
for i := 3 to 26 do //C to Z
begin
if mask and Drives <> 0 then
begin
H := CreateFile(PAnsiChar('\\.\' + Char(64 + i) + ':'), GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
if H <> INVALID_HANDLE_VALUE then
begin
SetLength(PartitionsInformation, Length(PartitionsInformation) + 1);
DeviceIoControl(H, IOCTL_DISK_GET_PARTITION_INFO, nil, 0, @PartitionsInformation[High(PartitionsInformation)], SizeOf(TPARTITION_INFORMATION), dwBytesReturned, nil);
CloseHandle(H);
end
else //removes unaccessible drives
DefineDosDevice(DDD_REMOVE_DEFINITION or DDD_RAW_TARGET_PATH, PAnsiChar(string(Char(64 + i) + ':')), nil);
end;
mask := mask shl 1;
end;
for i := 0 to 99 do
begin
H := CreateFile(PAnsiChar('\\.\PhysicalDrive' + IntToStr(i)), GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
if H = INVALID_HANDLE_VALUE then //no more hdd's
Break;
CloseHandle(H);
for j := 1 to 20 do
begin
BreakCycle := False;
NextLetter := GetNextAvailableLetter;
DefineDosDevice(DDD_RAW_TARGET_PATH or DDD_NO_BROADCAST_SYSTEM, PAnsiChar(string(NextLetter + ':')), PAnsiChar('\Device\Harddisk' + IntToStr(i) + '\Partition' + IntToStr(j)));
DoMount := True;
H := CreateFile(PAnsiChar('\\.\' + NextLetter + ':'), GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
if H = INVALID_HANDLE_VALUE then //no more partitions
BreakCycle := True
else
begin
PartitionInformation.PartitionType := 0;
DeviceIoControl(H, IOCTL_DISK_GET_PARTITION_INFO, nil, 0, @PartitionInformation, SizeOf(TPARTITION_INFORMATION), dwBytesReturned, nil);
DoMount := PartitionInformation.PartitionType in [0, 1, 6, 7, 11, 12, 114];
CloseHandle(H);
end;
if DoMount then
begin
for k := 0 to High(PartitionsInformation) do //compare with already mounted partitions
if (PartitionsInformation[k].StartingOffset.LowPart = PartitionInformation.StartingOffset.LowPart) and
(PartitionsInformation[k].StartingOffset.HighPart = PartitionInformation.StartingOffset.HighPart) and
(PartitionsInformation[k].StartingOffset.QuadPart = PartitionInformation.StartingOffset.QuadPart) and
(PartitionsInformation[k].PartitionLength.LowPart = PartitionInformation.PartitionLength.LowPart) and
(PartitionsInformation[k].PartitionLength.HighPart = PartitionInformation.PartitionLength.HighPart) and
(PartitionsInformation[k].PartitionLength.QuadPart = PartitionInformation.PartitionLength.QuadPart) and
(PartitionsInformation[k].HiddenSectors = PartitionInformation.HiddenSectors) and
(PartitionsInformation[k].PartitionType = PartitionInformation.PartitionType) and
(PartitionsInformation[k].BootIndicator = PartitionInformation.BootIndicator) and
(PartitionsInformation[k].RecognizedPartition = PartitionInformation.RecognizedPartition) then
Break;
DoMount := k > High(PartitionsInformation);
end;
DefineDosDevice(DDD_REMOVE_DEFINITION or DDD_RAW_TARGET_PATH, PAnsiChar(string(NextLetter + ':')), nil);
if (not BreakCycle) and DoMount then
DefineDosDevice(DDD_RAW_TARGET_PATH, PAnsiChar(string(NextLetter + ':')), PAnsiChar('\Device\Harddisk' + IntToStr(i) + '\Partition' + IntToStr(j)));
if BreakCycle then
Break;
end;
end;
SetErrorMode(OldMode); //restore original mode
end.
在我提到的计算机上,它运行得很好。
感谢各位帮助我制作此代码的所有想法。
如果有人发现了一些错误或者对如何改进它有任何好的想法,我会很乐意修复/实施它们。
答案 1 :(得分:2)
您可以使用WMI执行此操作
在库GLibWMI(http://neftali.clubdelphi.com或SourceForge)中,您可以找到 TDiskPartitionInfo 和 TDiskDriveInfo 。
第一个可以为您提供创建的分区和所有属性
测试通用样本并检查结果。在像这样的分区磁盘中:
您获得4个具有4个分区属性的实例,如下所示:
图书馆完全免费,可以获得资源。检查样品 您可以使用WMI找到一些其他代码来访问此信息。如果要使用其他,可以搜索“WMI和Win32_DiskPartition类”(Link doc)。
请原谅我的英语错误 此致
答案 2 :(得分:1)
也许我的Change DriveLetter命令行工具可以帮助您,至少您可以使用命令行参数启动它,看看它是否列出了您期望的所有卷。