using System; using System.Collections.Generic; using System.Management; using System.Text; namespace Trigger.Classes.Device { /// /// A disk that can store something /// public class StorageDisk : Device { #region Properties /// Number of bytes in one KB internal const uint KB = 1024; /// Number of bytes in one MB internal const uint MB = KB * 1024; /// Number of bytes in one GB internal const uint GB = MB * 1024; /// /// A list of s that are members of this /// public List Partitions = new List(); /// Gets the name of this disk. This is the Windows identifier, drive letter. public List DriveLetters { get { List letters = new List(Partitions.Count); Partitions.ForEach(new Action(partition => letters.Add(partition.DriveLetter))); return letters; } } /// Gets the total size of the disk, specified in bytes. public ulong Size { get; internal set; } /// Gets the available free space on the disk, specified in bytes. public ulong FreeSpace { get { ulong sum = 0; Partitions.ForEach(new Action(partition => sum += partition.FreeSpace)); return sum; } } #endregion #region Constructors /// /// Create a new from the letter /// /// public StorageDisk(int UnitMask) : base("") { char letter = FirstDriveFromMask(UnitMask); this.Id = ""; } /// /// Create a new from the corresponding /// /// public StorageDisk(ManagementObject mo) : base(mo["DeviceID"].ToString()) { this.Model = mo["Model"].ToString(); this.Name = mo["Name"].ToString(); this.Size = Convert.ToUInt64(mo["Size"]); } /// /// Create a new with the specified , and /// /// /// /// public StorageDisk(string Id, string Model, string Name) : base(Id) { this.Model = Model; this.Name = Name; } #endregion #region Methods #region Instance /// /// Pretty print the disk. /// /// public override string ToString() { StringBuilder builder = new StringBuilder(); builder.Append(this.Type.ToString()); builder.Append(": "); builder.Append(this.Model); builder.Append(" ("); builder.Append(StorageDisk.FormatByte(this.Size)); builder.Append(" in "); builder.Append(this.Partitions.Count); builder.Append(" partition"); if (this.Partitions.Count != 1) builder.Append("s"); builder.Append(")"); return builder.ToString(); } /// /// Adds a new partition /// /// public void AddPartition(Partition part) { this.Partitions.Add(part); } /// /// Compares this with another object /// /// /// public override bool Equals(object obj) { StorageDisk that = obj as StorageDisk; if (that == null) return false; return this.Type == that.Type && this.Name == that.Name; } /// /// Get a unique hashcode of this object /// /// public override int GetHashCode() { return this.DriveLetters.GetHashCode() ^ this.Type.GetHashCode() ^ this.Name.GetHashCode(); } #endregion #region Static /// /// Converts the specified amount of and returns a string where it is formatted as a human readable size /// /// /// public static string FormatByte(ulong bytes) { if (bytes < KB) return String.Format("{0} Bytes", bytes); else if (bytes < MB) return String.Format("{0} KB", (bytes / (float)KB).ToString("N")); else if (bytes < GB) return String.Format("{0} MB", (bytes / (float)MB).ToString("N1")); else return String.Format("{0} GB", (bytes / (float)GB).ToString("N1")); } /// /// Finds the first valid drive letter from a mask of drive letters. /// /// The mask must be in the format bit 0 = A, bit 1 = B, bit 2 = C, and so on. A valid drive letter is defined when the corresponding bit is set to 1. /// Returns the first drive letter that was found. internal static char FirstDriveFromMask(int unitmask) { int i; for (i = (char)0; i < 26; ++i) { if ((unitmask & 0x1) == 0x1) break; unitmask = unitmask >> 1; } return (char)(i + (int)'A'); } /// /// Creates a new from the specified /// /// /// internal static StorageDisk FromUnitMask(int UnitMask) { if (UnitMask == 0) return new StorageDisk(null, null, null); char Letter = FirstDriveFromMask(UnitMask); StorageDisk sd = null; ManagementObjectCollection partitions = new ManagementObjectSearcher(String.Format("ASSOCIATORS OF {{Win32_LogicalDisk.DeviceID='{0}:'}} WHERE AssocClass = Win32_LogicalDiskToPartition", Letter)).Get(); foreach (ManagementObject partition in partitions) { ManagementObjectCollection disks = new ManagementObjectSearcher(String.Format("ASSOCIATORS OF {{Win32_DiskPartition.DeviceID='{0}'}} WHERE AssocClass = Win32_DiskDriveToDiskPartition", partition["DeviceID"])).Get(); foreach (ManagementObject disk in disks) { sd = CreateStorageDiskFromDrive(disk); break; } } if (sd == null) { ManagementObjectCollection cdroms = new ManagementObjectSearcher(String.Format("SELECT * FROM Win32_CdRomDrive WHERE Drive = '{0}:\'", Letter)).Get(); foreach (ManagementObject cdrom in cdroms) { sd = new CdRomDrive(cdrom); break; } } ManagementObjectCollection volumes = new ManagementObjectSearcher(String.Format("SELECT * FROM Win32_LogicalDisk WHERE DeviceID = '{0}:'", Letter)).Get(); foreach (ManagementObject volume in volumes) { sd.AddPartition(new Partition(volume)); break; } return sd; } /// /// Gets all available disks /// /// public static List GetAvailableDisks() { return GetAvailableDisks(DeviceType.Any); } /// /// Gets all available disks of the specified /// /// /// public static List GetAvailableDisks(DeviceType Type) { string query = "SELECT * FROM Win32_DiskDrive"; if (Type != DeviceType.Any) query += " WHERE InterfaceType = '" + Type.ToString() + "'"; ManagementObjectCollection drives = new ManagementObjectSearcher(query).Get(); List disks = new List(); foreach (ManagementObject drive in drives) // browse all queried WMI physical disks { StorageDisk diskDrive = CreateStorageDiskFromDrive(drive); disks.Add(diskDrive); ManagementObjectCollection partitions = new ManagementObjectSearcher(String.Format("ASSOCIATORS OF {{Win32_DiskDrive.DeviceID='{0}'}} WHERE AssocClass = Win32_DiskDriveToDiskPartition", drive["DeviceID"])).Get(); // associate physical disks with partitions foreach (ManagementObject partition in partitions) { ManagementObjectCollection logicals = new ManagementObjectSearcher(String.Format("ASSOCIATORS OF {{Win32_DiskPartition.DeviceID='{0}'}} WHERE AssocClass = Win32_LogicalDiskToPartition", partition["DeviceID"])).Get(); // associate partitions with logical disks (drive letter volumes) foreach (ManagementObject logical in logicals) { ManagementObjectCollection volumes = new ManagementObjectSearcher(String.Format("SELECT * FROM Win32_LogicalDisk WHERE Name='{0}'", logical["Name"])).Get(); if (volumes.Count == 0) diskDrive.AddPartition(new Partition(logical)); else { foreach (ManagementObject volume in volumes) { diskDrive.AddPartition(new Partition(volume)); break; } } } } } return disks; } private static StorageDisk CreateStorageDiskFromDrive(ManagementObject drive) { switch ((DeviceType)Enum.Parse(typeof(DeviceType), drive["InterfaceType"].ToString())) { case DeviceType.USB: return new UsbDisk(drive); case DeviceType.IDE: return new IdeDisk(drive); default: return new StorageDisk(drive); } } #endregion #endregion } }