我在C#中编写了一个代码,使用WMI(System.Management)将逻辑驱动器映射到其物理磁盘。 代码工作得很好,但是像地狱一样缓慢。 在我的机器(Windows 7 x64,双核,3 GB RAM)中运行至少1秒。 1秒对我来说太慢了,甚至0.1都足以完成。 我不仅仅是痛苦,这个功能可以在不到0.1秒的时间内完成。
是否有任何可以提供帮助的Win32API功能?
还有其他建议吗?
到目前为止,这是我的代码:
List<Dictionary<string, string>> results = new List<Dictionary<string, string>>();
using (ManagementClass diskDriveClass = new ManagementClass(@"Win32_Diskdrive"))
{
using (ManagementObjectCollection diskDrives = diskDriveClass.GetInstances())
{
foreach (ManagementObject diskDrive in diskDrives)
{
string deviceId = (string)diskDrive["DeviceId"];
Dictionary<string, string> logicalDisksResults = new Dictionary<string, string>();
Trace.WriteLine(deviceId);
using (ManagementObjectCollection relatedPartitions = diskDrive.GetRelated("Win32_DiskPartition"))
{
foreach (ManagementObject relatedPartition in relatedPartitions)
{
Trace.WriteLine("-\t" + relatedPartition["Name"]);
using (ManagementObjectCollection relatedLogicalDisks = relatedPartition.GetRelated("Win32_LogicalDisk"))
{
foreach (ManagementBaseObject relatedLogicalDisk in
relatedLogicalDisks)
{
Trace.WriteLine("\t-\t" + relatedLogicalDisk["Name"] + " " + relatedLogicalDisk["FileSystem"]);
logicalDisksResults.Add((string)relatedLogicalDisk["Name"], (string)relatedLogicalDisk["FileSystem"]);
}
}
}
}
results.Add(logicalDisksResults);
}
}
}
答案 0 :(得分:1)
这里有一些代码,至少在我的系统上运行(从客观的角度来看)更快,并给出相同的结果。由于驱动器列表几乎不可能逐秒改变,我不确定为什么你真的非常关心,但无论如何,看看这是否让你更快乐。您可以通过删除在开始时获取Win32_DiskDrive的代码来稍微加快速度,运气好,让它在0.1秒内运行:)
Dictionary<string, Dictionary<string, string>> results = new Dictionary<string,Dictionary<string,string>>(); ManagementClass diskPartMap = null; ManagementObjectCollection diskPartIns = null; ManagementClass partLogicalMap = null; ManagementObjectCollection partLogicalIns = null; try { using (ManagementClass diskDriveClass = new ManagementClass("Win32_Diskdrive")) { using (ManagementObjectCollection diskDrives = diskDriveClass.GetInstances()) { foreach (ManagementObject diskDrive in diskDrives) { results.Add((string)diskDrive["DeviceId"], new Dictionary<string, string>()); } } } Dictionary<string, ManagementObject> partToDisk = new Dictionary<string, ManagementObject>(); Dictionary<string, ManagementObject> partToLogical = new Dictionary<string, ManagementObject>(); diskPartMap = new ManagementClass("Win32_DiskDriveToDiskPartition"); diskPartIns = diskPartMap.GetInstances(); foreach (ManagementObject diskDrive in diskPartIns) { ManagementObject o = new ManagementObject((string)diskDrive["Antecedent"]); partToDisk.Add((string)diskDrive["Dependent"], o); } partLogicalMap = new ManagementClass("Win32_LogicalDiskToPartition"); partLogicalIns = partLogicalMap.GetInstances(); foreach (ManagementObject diskDrive in partLogicalIns) { ManagementObject o = new ManagementObject((string)diskDrive["Dependent"]); string s = (string)diskDrive["Antecedent"]; partToLogical.Add(s, o); } foreach (KeyValuePair<string, ManagementObject> pair in partToDisk) { string deviceId = (string)pair.Value["DeviceId"]; Dictionary<string, string> dict = null; if (!results.ContainsKey(deviceId)) { dict = new Dictionary<string, string>(); results[deviceId] = dict; } else { dict = results[deviceId]; } if (partToLogical.ContainsKey(pair.Key)) { ManagementObject o = partToLogical[pair.Key]; dict.Add((string)o["Name"], (string)o["FileSystem"]); } } } finally { if (diskPartIns != null) { diskPartIns.Dispose(); diskPartIns = null; } if (diskPartMap != null) { diskPartMap.Dispose(); diskPartMap = null; } if (partLogicalIns != null) { partLogicalIns.Dispose(); partLogicalIns = null; } if (partLogicalMap != null) { partLogicalMap.Dispose(); partLogicalMap = null; } }
答案 1 :(得分:1)
这是我的最终代码,x23比第一个版本快,基于使用Win32_LogicalDiskToPartition的tyranid想法。
private static Regex _logicalDiskNameRegex = new Regex("(?<=\")[^\"]*(?=\")");
private static Regex _partitionDiskIndexRegex = new Regex("(?<=\"Disk #)\\d+");
public static Dictionary<string, string>[] GetPhisicalHardDiskToDriveLettersMap()
{
DriveInfo[] driveInfoArr = DriveInfo.GetDrives();
DriveInfo lastDriveInfo = null;
Dictionary<string, DriveInfo> driveInfos = new Dictionary<string, DriveInfo>(driveInfoArr.Length);
foreach (DriveInfo driveInfo in driveInfoArr)
{
if (driveInfo.DriveType == DriveType.Fixed)
{
driveInfos.Add(driveInfo.Name.Substring(0, 2), driveInfo);
lastDriveInfo = driveInfo;
}
}
if (driveInfos.Count == 1 && lastDriveInfo != null)
{
return new Dictionary<string, string>[]
{
new Dictionary<string, string>()
{
{lastDriveInfo.Name.Substring(0, 2), lastDriveInfo.DriveFormat}
}
};
}
Dictionary<string, Dictionary<string, string>> results = new Dictionary<string, Dictionary<string, string>>();
using (ManagementClass partLogicalMap = new ManagementClass("Win32_LogicalDiskToPartition"))
{
using (ManagementObjectCollection partLogicalIns = partLogicalMap.GetInstances())
{
foreach (ManagementObject diskDrive in partLogicalIns)
{
bool lazySuccess = false;
string driveName = null;
string driveFileSystem = null;
string physicalHardDisk = null;
string logicalDiskPath = (string)diskDrive["Dependent"];
string partitionPath = (string)diskDrive["Antecedent"];
Trace.WriteLine(logicalDiskPath);
Trace.WriteLine(partitionPath);
Match logicalDiskNameMatch = _logicalDiskNameRegex.Match(logicalDiskPath);
if (logicalDiskNameMatch.Success)
{
Match partitionDiskIndexMatch = _partitionDiskIndexRegex.Match(partitionPath);
if (partitionDiskIndexMatch.Success)
{
try
{
driveName = logicalDiskNameMatch.Value;
physicalHardDisk = partitionDiskIndexMatch.Value;
driveFileSystem = driveInfos[driveName].DriveFormat;
lazySuccess = true;
}
catch (Exception ex)
{
Trace.WriteLine(ex.ToString());
}
}
}
if (!lazySuccess)
{
// old good code but less performance, to be on the safe side if lazy method fails.
ManagementObject logicalDiskObject = new ManagementObject(logicalDiskPath);
ManagementObject partitionObject = new ManagementObject(partitionPath);
driveName = (string)logicalDiskObject["Name"];
driveFileSystem = (string)logicalDiskObject["FileSystem"];
physicalHardDisk = partitionObject["DiskIndex"].ToString();
}
Dictionary<string, string> hardDiskDrives;
if (!results.TryGetValue(physicalHardDisk, out hardDiskDrives))
{
hardDiskDrives = new Dictionary<string, string>();
results.Add(physicalHardDisk, hardDiskDrives);
}
hardDiskDrives.Add(driveName, driveFileSystem);
}
}
}
return ToArray(results.Values);
}
答案 2 :(得分:1)
我发现最好的方法是从4个类中获取完整数据然后再加入LINQ以最小化对WMI服务的影响(因为它在负载下很慢)。
首先你可能认为这听起来很糟糕,但要测试一下,看看我在谈论什么。
答案 3 :(得分:0)
请参阅this article(包含代码示例),了解GetLogicalDrives,GetLogicalDriveStrings,GetDriveType和GetVolumeInformation
要查找物理驱动器,您可以使用FindFirstVolume
和FindNextVolume
(我得到“\。\ Device {uiid}”。与GetVolumePathNamesForVolumeNameW
结合使用以获取相关的驱动器号。然后您可以使用上述API获取所需信息。
如果您需要分区/磁盘编号,请参阅DeviceIoControl以获取该信息
我认为您需要代码results
中的内容。