3

我用 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);
        }
    }
}
4

4 回答 4

1

那么这里有一些代码至少在我的系统上运行(从客观的角度来看)更快并给出相同的结果。由于驱动器列表几乎不可能每秒更改,我不确定您为什么如此关心,但无论如何,看看这是否让您更快乐。您可以通过删除开始时获取 Win32_DiskDrive 的代码来稍微加快速度,但祝它在 0.1 秒内运行 :)

Dictionary<string, Dictionary<string, string>> 结果 = new Dictionary<string,Dictionary<string,string>>();            

ManagementClass diskPartMap = null;
ManagementObjectCollection diskPartIns = null;
ManagementClass partLogicalMap = null;
ManagementObjectCollection partLogicalIns = null;

尝试
{
    使用 (ManagementClass diskDriveClass = new ManagementClass("Win32_Diskdrive"))
    {
        使用 (ManagementObjectCollection diskDrives = diskDriveClass.GetInstances())
        {
            foreach(磁盘驱动器中的管理对象磁盘驱动器)
            {
                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(diskPartIns 中的 ManagementObject diskDrive)
    {
        ManagementObject o = new ManagementObject((string)diskDrive["Antecedent"]);
        partToDisk.Add((string)diskDrive["Dependent"], o);
    }

    partLogicalMap = new ManagementClass("Win32_LogicalDiskToPartition");
    partLogicalIns = partLogicalMap.GetInstances();
    foreach(部分LogicalIns中的ManagementObject diskDrive)
    {
        ManagementObject o = new ManagementObject((string)diskDrive["Dependent"]);
        string s = (string)diskDrive["Antecedent"];

        partToLogical.Add(s, o);
    }

    foreach(partToDisk 中的 KeyValuePair<string, ManagementObject> 对)
    {
        string deviceId = (string)pair.Value["DeviceId"];
        字典<字符串,字符串> dict = null;
        if (!results.ContainsKey(deviceId))
        {
            dict = new Dictionary<string, string>();
            结果[deviceId] = 字典;
        }
        别的
        {
            dict = 结果[deviceId];
        }

        if (partToLogical.ContainsKey(pair.Key))
        {
            ManagementObject o = partToLogical[pair.Key];
            dict.Add((string)o["Name"], (string)o["FileSystem"]);
        }
    }
}
最后
{
    if (diskPartIns != null)
    {
        diskPartIns.Dispose();
        diskPartIns = null;
    }

    if (diskPartMap != null)
    {
        diskPartMap.Dispose();
        磁盘部分映射 = 空;
    }

    if (partLogicalIns != null)
    {
        partLogicalIns.Dispose();
        partLogicalIns = null;
    }

    if (partLogicalMap != null)
    {
        partLogicalMap.Dispose();
        部分逻辑映射=空;
    }
}
于 2009-11-25T00:16:45.790 回答
1

这是我的最终代码,x23 比第一个版本快,基于 tyranid 想法使用 Win32_LogicalDiskToPartition。

    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);
    }
于 2009-11-25T20:01:35.570 回答
1

我发现最好的方法是从 4 个类中的每一个中获取完整数据,然后加入 LINQ 以尽量减少对 WMI 服务的影响(因为它在负载下很慢)。

首先,您可能会认为这听起来很可怕,但请测试一下,看看我在说什么。

于 2011-12-09T20:41:11.377 回答
0

请参阅有关 GetLogicalDrives、GetLogicalDriveStrings、GetDriveType 和 GetVolumeInformation 的这篇文章(带有代码示例)

要查找物理驱动器,您可以使用FindFirstVolumeand FindNextVolume(I get "\.\Device{uiid}"。结合GetVolumePathNamesForVolumeNameW以获取关联的驱动器号。然后您可以使用上述 API 获取所需的信息。如果您需要分区/磁盘数字请参阅DeviceIoControl以获取该信息

我以为您需要results代码中的内容。

于 2009-11-23T05:39:47.133 回答