2009-11-20 86 views
3

我在C#中編寫了一個代碼,它使用WMI(System.Management)將邏輯驅動器映射到其物理磁盤。代碼工作完美,但像地獄一樣慢。 在我的機器(Windows 7 x64,雙核3 GB RAM)中,它至少運行1秒。對我來說,1秒對我來說太慢了,即使0.1也足夠完成了。 我不止一次覺得這個功能可以在0.1秒內完成。WMI性能差

有沒有可以幫助的任何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

請問您可以發佈您的選項定義嗎? – 2009-11-22 22:50:47

+0

不好意思,我修正了上面的代碼。我最初使用沒有選項,我只是試圖提高性能,但這並沒有幫助。 – DxCK 2009-11-23 05:20:53

回答

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; 
    } 
} 
+0

非常感謝,你幫了我很多! :-)你的代碼在我的機器上運行比我的速度快4倍。另外,根據您對Win32_LogicalDiskToPartition的想法,我成功地使性能更好,現在它的運行速度比我的第一個版本快了23倍。 :d – DxCK 2009-11-25 19:55:35

0

看到this article(與代碼示例)約GetLogicalDrives,GetLogicalDriveStrings,GetDriveType和GetVolumeInformation

要查找物理驅動器,你可以使用FindFirstVolumeFindNextVolume(我得到了「\。\ Device {uiid}」,與GetVolumePathNamesForVolumeNameW結合得到關聯的驅動器號,然後你可以通過上面提到的API得到你想要的信息 如果你需要分區/磁盤號,請參考DeviceIoControl得到那個信息

我以爲你需要什麼在results在你的代碼。

+0

謝謝,但這並沒有多大幫助。是否有類似的功能可以幫助在邏輯驅動器及其物理磁盤之間進行映射? – DxCK 2009-11-23 19:34:25

1

這是我最後的代碼,X23比第一版本運行速度的基礎上,蟲族的想法使用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); 
    } 
1

我發現,最好的路線是從各4班得到完整的數據,然後做LINQ您的加盟,以儘量減少對WMI服務的影響(因爲它是在負載下慢)。作爲第一個你可能會認爲聽起來很糟糕,但測試它看看我在說什麼。