3

WMI (System.Management) を使用して論理ドライブを物理ディスクにマップするコードを C# で作成しました。コードは完全に機能していますが、地獄のように遅いです。私のマシン (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

さて、少なくとも私のシステムでは(客観的な観点から)より速く実行され、同じ結果が得られるコードがあります。ドライブのリストが 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;

試す
{
    using (ManagementClass diskDriveClass = new ManagementClass("Win32_Diskdrive"))
    {
        使用 (ManagementObjectCollection diskDrives = diskDriveClass.GetInstances())
        {
            foreach (diskDrives 内の ManagementObject diskDrive)
            {
                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["従属"], o);
    }

    partLogicalMap = new ManagementClass("Win32_LogicalDiskToPartition");
    partLogicalIns = partLogicalMap.GetInstances();
    foreach (partLogicalIns の 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"];
        Dictionary<string, string> dict = null;
        if (!results.ContainsKey(deviceId))
        {
            dict = 新しい Dictionary<string, string>();
            結果[deviceId] = dict;
        }
        そうしないと
        {
            dict = 結果[deviceId];
        }

        if (partToLogical.ContainsKey(pair.Key))
        {
            ManagementObject o = partToLogical[pair.Key];
            dict.Add((文字列)o["名前"], (文字列)o["ファイルシステム"]);
        }
    }
}
最後に
{
    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;
    }
}
于 2009-11-25T00:16:45.790 に答える
1

これは私の最終的なコードで、Win32_LogicalDiskToPartition を使用するという極端なアイデアに基づいており、最初のバージョンよりも 23 倍高速です。

    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 に答える