目前我使用以下代码获取硬盘的序列号:
private void GetAllDiskDrives()
{
var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
foreach (ManagementObject wmi_HD in searcher.Get())
{
HardDrive hd = new HardDrive();
hd.Model = wmi_HD["Model"].ToString();
hd.InterfaceType = wmi_HD["InterfaceType"].ToString();
hd.SerialNo = wmi_HD.GetPropertyValue("SerialNumber").ToString();//get the serailNumber of diskdrive
HdCollection.Add(hd);
}
}
public class HardDrive
{
public string Model { get; set; }
public string InterfaceType { get; set; }
public string SerialNo { get; set; }
}
此代码工作正常。
但是上面的代码返回了所有的驱动器。我只想要运行我的软件的特定硬盘驱动器(Not Partition)序列号。
那么,如何获取运行我的软件的硬盘序列号?
答案 0 :(得分:6)
使用SELECT * FROM Win32_PhysicalMedia
查找所有物理驱动器。
要查找从中加载程序的物理驱动器,您必须从System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase
中提取驱动器号,然后使用SELECT * FROM Win32_DiskDrive
加载所有分区,然后以某种方式将所需的分区映射到其中一个物理分区从SELECT * FROM Win32_PhysicalMedia
开车。
我进一步研究了你的问题。使用WMI似乎无法关联分区和物理驱动器。但直接使用WinAPI它是一块蛋糕:
[DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern Boolean GetVolumeNameForVolumeMountPoint(String mountPoint, StringBuilder name, UInt32 bufferLength);
private enum FileAccess : uint
{
GenericReadWrite = 0x80000000 | 0x40000000 // GENERIC_READ | GENERIC_WRITE
}
private enum FileShare : uint
{
ReadWriteDelete = 0x00000001 | 0x00000002 | 0x00000004 // FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE
}
private enum FileCreation : uint
{
OpenExisting = 3 // OPEN_EXISTING
}
private enum FileFlags : uint
{
None = 0
}
[DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CreateFile(String fileName, FileAccess access, FileShare share, IntPtr secAttr,
FileCreation creation, FileFlags flags, IntPtr templateFile);
[DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern Boolean CloseHandle(IntPtr handle);
private enum IoControlCode
{
GetVolumeDiskExtents = 0x00560000 // IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
}
[StructLayout(LayoutKind.Explicit)]
private struct VolumeDiskExtents
{
[FieldOffset(0)]
public UInt32 numberOfDiskExtents;
[FieldOffset(8)]
public UInt32 diskNumber;
[FieldOffset(16)]
public Int64 startingOffset;
[FieldOffset(24)]
public Int64 extentLength;
}
[DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern Boolean DeviceIoControl(IntPtr device, IoControlCode controlCode, IntPtr inBuffer, UInt32 inBufferSize,
ref VolumeDiskExtents extents, UInt32 outBufferSize, ref UInt32 bytesReturned, IntPtr overlapped);
public class PhysicalDisk
{
public PhysicalDisk(String physicalName, String model, String interfaceType, String serialNumber)
{
this.PhysicalName = physicalName;
this.Model = model;
this.InterfaceType = interfaceType;
this.SerialNumber = serialNumber;
}
public String PhysicalName { get; private set; }
public String Model { get; private set; }
public String InterfaceType { get; private set; }
public String SerialNumber { get; private set; }
}
public PhysicalDisk GetPhysicalDiskFromCurrentDrive()
{
//
// Get the drive letter of the drive the executable was loaded from.
//
var basePath = System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase.Replace("file:///", "");
var driveLetter = System.IO.Path.GetPathRoot(basePath);
// TODO: Validate driveLetter; could also be a UNC path.
//
// Get the volume name of the drive letter.
//
var volumeNameBuffer = new StringBuilder(65536);
if (!GetVolumeNameForVolumeMountPoint(driveLetter, volumeNameBuffer, (UInt32)volumeNameBuffer.Capacity))
throw new Win32Exception();
var volumeName = volumeNameBuffer.ToString().TrimEnd('\\'); // Remove trailing backslash
//
// Open the volume and retrieve the disk number.
//
UInt32 diskNumber;
IntPtr volume = IntPtr.Zero;
try
{
volume = CreateFile(volumeName, FileAccess.GenericReadWrite, FileShare.ReadWriteDelete, IntPtr.Zero,
FileCreation.OpenExisting, FileFlags.None, IntPtr.Zero);
if (volume == (IntPtr)(-1)) // INVALID_HANDLE_VALUE
{
volume = IntPtr.Zero;
throw new Win32Exception();
}
VolumeDiskExtents extents = new VolumeDiskExtents();
UInt32 bytesReturned = 0;
if (!DeviceIoControl(volume, IoControlCode.GetVolumeDiskExtents, IntPtr.Zero, 0,
ref extents, (UInt32)Marshal.SizeOf(extents), ref bytesReturned, IntPtr.Zero))
{
// Partitions can span more than one disk, we will ignore this case for now.
// See http://msdn.microsoft.com/en-us/library/windows/desktop/aa365727(v=vs.85).aspx
if (Marshal.GetLastWin32Error() != 234 /*ERROR_MORE_DATA*/)
throw new Win32Exception();
}
diskNumber = extents.diskNumber;
}
finally
{
if (volume != IntPtr.Zero)
{
CloseHandle(volume);
volume = IntPtr.Zero;
}
}
//
// Build the physical disk name from the disk number.
//
String physicalName = ("\\\\.\\PHYSICALDRIVE" + diskNumber).Replace("\\", "\\\\");
//
// Find information about the physical disk using WMI.
//
var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive WHERE DeviceID = \"" + physicalName + "\"");
foreach (ManagementObject obj in searcher.Get())
{
return new PhysicalDisk(
obj["DeviceID"].ToString(),
obj["Model"].ToString(),
obj["InterfaceType"].ToString(),
obj["SerialNumber"].ToString()
);
}
throw new InvalidOperationException();
}