如何获得硬盘的SerialNumber在C#中(不WMI)?

我知道在CodeProject上的两篇文章(一个使用WMI和其他没有WMI但在C ++)。 我试过WMI方式,不仅是缓慢的,但也是不可靠的。 所以,这就是为什么我决定放弃这种方式。 我想通过的PInvoke做到这一点在C#。 我尝试过,但陷入了DeviceIoControl的API。 任何人都可以给我一个提示? 这里是我的代码:

using System; using System.ComponentModel; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; using Microsoft.Win32.SafeHandles; namespace Chemulator.Common { public class HDSerialNumber { [StructLayout(LayoutKind.Sequential)] private struct IDEREGS { public byte bFeaturesReg; public byte bSectorCountReg; public byte bSectorNumberReg; public byte bCylLowReg; public byte bCylHighReg; public byte bDriveHeadReg; public byte bCommandReg; public byte bReserved; } [StructLayout(LayoutKind.Sequential)] private struct SENDCMDINPARAMS { public Int32 cBufferSize; public IDEREGS irDriveRegs; public byte bDriveNumber; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] bReserved; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public Int32[] dwReserved; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] public byte[] bBuffer; } [StructLayout(LayoutKind.Sequential)] private struct DRIVERSTATUS { public byte bDriverError; public byte bIDEError; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] bReserved; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public Int32[] dwReserved; } [StructLayout(LayoutKind.Sequential)] private struct SENDCMDOUTPARAMS { public Int32 cBufferSize; public DRIVERSTATUS DriverStatus; [MarshalAs(UnmanagedType.ByValArray, SizeConst = IDENTIFY_BUFFER_SIZE)] public byte[] bBuffer; } [StructLayout(LayoutKind.Sequential)] private struct GETVERSIONOUTPARAMS { public byte bVersion; public byte bRevision; public byte bReserved; public byte bIDEDeviceMap; public Int32 fCapabilities; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public Int32 dwReserved; } [StructLayout(LayoutKind.Sequential)] private struct STORAGE_PROPERTY_QUERY { public Int32 PropertyId; public Int32 QueryType; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] public byte[] AdditionalParameters; } [StructLayout(LayoutKind.Sequential)] private struct STORAGE_DEVICE_DESCRIPTOR { public Int32 Version; public Int32 Size; public byte DeviceType; public byte DeviceTypeModifier; public byte RemovableMedia; public byte CommandQueueing; public Int32 VendorIdOffset; public Int32 ProductIdOffset; public Int32 ProductRevisionOffset; public Int32 SerialNumberOffset; public byte BusType; public Int32 RawPropertiesLength; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10240)] public byte[] RawDeviceProperties; } [DllImport("kernel32.dll", SetLastError = true)] private static extern SafeFileHandle CreateFile(string lpFileName, Int32 dwDesiredAccess, Int32 dwShareMode, IntPtr lpSecurityAttributes, Int32 dwCreationDisposition, Int32 dwFlagsAndAttributes, IntPtr hTemplateFile); [DllImport("kernel32")] private static extern bool DeviceIoControl(SafeFileHandle hDevice, uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize, IntPtr lpOutBuffer, uint nOutBufferSize, ref uint lpBytesReturned, IntPtr lpOverlapped); private const Int32 OPEN_EXISTING = 3; private const Int32 GENERIC_READ = unchecked((int)0x80000000); private const Int32 GENERIC_WRITE = 0x40000000; private const Int32 FILE_SHARE_READ = 0x1; private const Int32 FILE_SHARE_WRITE = 0x2; private const Int32 FILE_SHARE_DELETE = 0x4; private const Int32 SMART_GET_VERSION = 0x74080; private const Int32 SMART_RCV_DRIVE_DATA = 0x7C088; private const Int32 ID_CMD = 0xEC; private const Int32 IDENTIFY_BUFFER_SIZE = 512; private const Int32 CAP_SMART_CMD = 0x4; private const Int32 IOCTL_STORAGE_QUERY_PROPERTY = 0x2D1400; private const Int32 PropertyStandardQuery = 0; private const Int32 StorageDeviceProperty = 0; public static string GetSerialNumber(int diskNumber) { string str = GetSerialNumberUsingStorageQuery(diskNumber); if (string.IsNullOrEmpty(str)) str = GetSerialNumberUsingSmart(diskNumber); return str; } public static string GetSerialNumberUsingStorageQuery(int diskNumber) { using (SafeFileHandle hDisk = OpenDisk(diskNumber)) { uint iBytesReturned = 0; var spq = new STORAGE_PROPERTY_QUERY(); var sdd = new STORAGE_DEVICE_DESCRIPTOR(); spq.PropertyId = StorageDeviceProperty; spq.QueryType = PropertyStandardQuery; if (DeviceIoControl(hDisk, IOCTL_STORAGE_QUERY_PROPERTY, spq, (uint)Marshal.SizeOf(spq), sdd, (uint)Marshal.SizeOf(sdd), ref iBytesReturned, IntPtr.Zero)) throw CreateWin32Exception(Marshal.GetLastWin32Error(), "DeviceIoControl(IOCTL_STORAGE_QUERY_PROPERTY)"); var result = new StringBuilder(); if (sdd.SerialNumberOffset > 0) { var rawDevicePropertiesOffset = Marshal.SizeOf(sdd) - sdd.RawDeviceProperties.Length; int pos = sdd.SerialNumberOffset - rawDevicePropertiesOffset; while (pos < iBytesReturned && sdd.RawDeviceProperties[pos] != 0) { result.Append(Encoding.ASCII.GetString(sdd.RawDeviceProperties, pos, 1)); pos += 1; } } return result.ToString(); } } public static string GetSerialNumberUsingSmart(int diskNumber) { using (SafeFileHandle hDisk = OpenDisk(diskNumber)) { if (IsSmartSupported(hDisk)) { Int32 iBytesReturned = 0; var sci = new SENDCMDINPARAMS(); var sco = new SENDCMDOUTPARAMS(); sci.irDriveRegs.bCommandReg = ID_CMD; sci.bDriveNumber = (byte)diskNumber; sci.cBufferSize = IDENTIFY_BUFFER_SIZE; if (DeviceIoControl(hDisk, SMART_RCV_DRIVE_DATA, sci, (uint)Marshal.SizeOf(sci), sco, (uint)Marshal.SizeOf(sco), ref iBytesReturned, IntPtr.Zero)) throw CreateWin32Exception(Marshal.GetLastWin32Error(), "DeviceIoControl(SMART_RCV_DRIVE_DATA)"); var result = new StringBuilder(); for (int index = 20; index < 39; index += 2) { result.Append(Encoding.ASCII.GetString(sco.bBuffer, index + 1, 1)); result.Append(Encoding.ASCII.GetString(sco.bBuffer, index, 1)); } return result.ToString(); } return string.Empty; } } private static Win32Exception CreateWin32Exception(Int32 errorCode, string context) { var win32Exception = new Win32Exception(errorCode); win32Exception.Data["Context"] = context; return win32Exception; } private static SafeFileHandle OpenDisk(int diskNumber) { SafeFileHandle hDevice = CreateFile(string.Format(@"\\.\PhysicalDrive{0}", diskNumber), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); if (!hDevice.IsInvalid) return hDevice; else throw CreateWin32Exception(Marshal.GetLastWin32Error(), "CreateFile"); } private static bool IsSmartSupported(SafeFileHandle hDisk) { uint iBytesReturned = 0; var gvo = new GETVERSIONOUTPARAMS(); IntPtr pGVO = Marshal.AllocHGlobal(512); if (DeviceIoControl(hDisk, SMART_GET_VERSION, IntPtr.Zero, 0, pGVO, 512, ref iBytesReturned, IntPtr.Zero)) return false; return (gvo.fCapabilities & CAP_SMART_CMD) > 0; } } }

--------------解决方案-------------

退房有关的DeviceIoControl的pinvoke.net教程。

向下滚动页面,在这里你可以看到VB .NET 3.0完整的例子(感谢“bogdandaniel”)的编辑pPumkiN。 这是访问不同影响IO设备的完整的例子。 我beleieve有DRIVE_INFO了。

另外我没有任何这方面的经验。 试一试

分类:C# 时间:2015-03-15 人气:0
分享到:

相关文章

Copyright (C) 55228885.com, All Rights Reserved.

55228885 版权所有 京ICP备15002868号

processed in 1.073 (s). 10 q(s)