NET获取硬盘序列号的几个方法.docx
《NET获取硬盘序列号的几个方法.docx》由会员分享,可在线阅读,更多相关《NET获取硬盘序列号的几个方法.docx(18页珍藏版)》请在冰豆网上搜索。
![NET获取硬盘序列号的几个方法.docx](https://file1.bdocx.com/fileroot1/2023-1/14/46bb85c5-7fbb-4da5-9f8c-4b27abf87239/46bb85c5-7fbb-4da5-9f8c-4b27abf872391.gif)
NET获取硬盘序列号的几个方法
最近作软件注册,收集了很多.NET相关的获取硬盘物理序列号的方法,主要分为使用WMI方式和API方式。
但这些方法均可能有问题。
1,使用WMI方式,有的机器根本取不到硬盘序列号,有的方式在Vista下面会报错。
常用的使用WMI的方式主要有下面一些方式:
classHardDrive
{
privatestringmodel=null;
privatestringtype=null;
privatestringserialNo=null;
publicstringModel
{
get{returnmodel;}
set{model=value;}
}
publicstringType
{
get{returntype;}
set{type=value;}
}
publicstringSerialNo
{
get{returnserialNo;}
set{serialNo=value;}
}
}
classTestProgram
{
///
///Themainentrypointfortheapplication.
///
[STAThread]
staticvoidMain(string[]args)
{
//在Vista下面失败
ArrayListhdCollection=newArrayList();
ManagementObjectSearchersearcher=new
ManagementObjectSearcher("SELECT*FROMWin32_DiskDrive");
foreach(ManagementObjectwmi_HDinsearcher.Get())
{
HardDrivehd=newHardDrive();
hd.Model=wmi_HD["Model"].ToString();
hd.Type=wmi_HD["InterfaceType"].ToString();
hdCollection.Add(hd);
}
searcher=new
ManagementObjectSearcher("SELECT*FROMWin32_PhysicalMedia");
inti=0;
foreach(ManagementObjectwmi_HDinsearcher.Get())
{
//gettheharddrivefromcollection
//usingindex
HardDrivehd=(HardDrive)hdCollection[i];
//getthehardwareserialno.
if(wmi_HD["SerialNumber"]==null)
hd.SerialNo="None";
else
hd.SerialNo=wmi_HD["SerialNumber"].ToString();
++i;
}
//Displayavailableharddrives
foreach(HardDrivehdinhdCollection)
{
Console.WriteLine("Model\t\t:
"+hd.Model);
Console.WriteLine("Type\t\t:
"+hd.Type);
Console.WriteLine("SerialNo.\t:
"+hd.SerialNo);
Console.WriteLine();
}
//Pauseapplication
Console.WriteLine("Press[Enter]toexit...");
Console.ReadLine();
}
}
上面的方式先查询Win32_DiskDrive,然后再查询Win32_PhysicalMedia,经过测试,这种方式不能保证在所有机器上均取得硬盘序列号,而且在Vista下面还会出错,程序直接抛出无法处理的异常。
另外,还可以使用另外一WMI方式,就是查询PNPDeviceID的signature,代码如下:
///
///获取硬盘唯一序列号(不是卷标号),可能需要以管理员身份运行程序
///
///
publicstaticstringGetHdId()
{
ManagementObjectSearcherwmiSearcher=newManagementObjectSearcher();
/*
*PNPDeviceID的数据是由四部分组成的:
1、接口,通常有IDE,ATA,SCSI;
2、型号
3、(可能)驱动版本号
4、(可能)硬盘的出厂序列号
*
*
*/
//signature需要程序以管理员身份运行(经过测试,2003系统上非管理员身份也可以运行,查相关资料说,可能在2000系统上获取的值为空)
wmiSearcher.Query=newSelectQuery(
"Win32_DiskDrive",
"",
newstring[]{"PNPDeviceID","signature"}
);
ManagementObjectCollectionmyCollection=wmiSearcher.Get();
ManagementObjectCollection.ManagementObjectEnumeratorem=
myCollection.GetEnumerator();
em.MoveNext();
ManagementBaseObjectmo=em.Current;
//stringid=mo.Properties["PNPDeviceID"].Value.ToString().Trim();
stringid=mo.Properties["signature"].Value.ToString().Trim();
returnid;
}
有人说,使用signature需要程序以管理员身份运行(经过测试,2003系统上非管理员身份也可以运行),而且查询相关资料说,可能在2000系统上获取的值为空。
使用这种方式,在Vista上面工作良好。
经过测试,使用signature均能够取得硬盘序列号,但是跟Win32_PhysicalMedia查询出来的号不一样。
目前我也不能肯定使用signature能够100%取道硬盘序列号。
使用WMI方式需要客户机开启WMI服务,但这个往往不能保证,所以使用这种方式有一定局限性。
2,使用API方式。
在网上找到一片资料,说使用RING3调用APIDeviceIoControl()来获取硬盘信息,下面是原话:
硬盘序列号(SerialNumber)不等于卷标号(VolumeName),后者虽然很容易得到,但是格式化分区后就会重写,不可靠。
遗憾的是很多朋友往往分不清这一点。
要得到硬盘的物理序列号,可以通过WMI,也就是Win32_PhysicalMedia.SerialNumber。
可惜的是Windows98/ME的WMI并不支持这个类,访问时会出现异常。
受陆麟的例子的启发,我们还可以通过S.M.A.R.T.接口,直接从RING3调用APIDeviceIoControl()来获取硬盘信息,而不需要写VXD或者DRIVER。
这样这个问题就解决了,我对它进行了封装,大量使用了P/Invoke技术,一个完整的Library。
支持Windows98-2003。
使用上很简单:
HardDiskInfohdd=AtapiDevice.GetHddInfo(0);//第一个硬盘
Console.WriteLine("ModuleNumber:
{0}",hdd.ModuleNumber);
Console.WriteLine("SerialNumber:
{0}",hdd.SerialNumber);
Console.WriteLine("Firmware:
{0}",hdd.Firmware);
Console.WriteLine("Capacity:
{0}M",hdd.Capacity);
感谢原文作者的贡献,(在这里我已经不知道原文作者是谁了,网上的文章都是转载的),经过测试,这种方式比较准确,但是需要管理员权限运行。
下面把代码分享:
usingSystem;
usingSystem.Runtime.InteropServices;
usingSystem.Text;
namespaceHardwareUtility
{
[Serializable]
publicstructHardDiskInfo
{
///
///型号
///
publicstringModuleNumber;
///
///固件版本
///
publicstringFirmware;
///
///序列号
///
publicstringSerialNumber;
///
///容量,以M为单位
///
publicuintCapacity;
}
#regionInternalStructs
[StructLayout(LayoutKind.Sequential,Pack=1)]
internalstructGetVersionOutParams
{
publicbytebVersion;
publicbytebRevision;
publicbytebReserved;
publicbytebIDEDeviceMap;
publicuintfCapabilities;
[MarshalAs(UnmanagedType.ByValArray,SizeConst=4)]
publicuint[]dwReserved;//Forfutureuse.
}
[StructLayout(LayoutKind.Sequential,Pack=1)]
internalstructIdeRegs
{
publicbytebFeaturesReg;
publicbytebSectorCountReg;
publicbytebSectorNumberReg;
publicbytebCylLowReg;
publicbytebCylHighReg;
publicbytebDriveHeadReg;
publicbytebCommandReg;
publicbytebReserved;
}
[StructLayout(LayoutKind.Sequential,Pack=1)]
internalstructSendCmdInParams
{
publicuintcBufferSize;
publicIdeRegsirDriveRegs;
publicbytebDriveNumber;
[MarshalAs(UnmanagedType.ByValArray,SizeConst=3)]
publicbyte[]bReserved;
[MarshalAs(UnmanagedType.ByValArray,SizeConst=4)]
publicuint[]dwReserved;
publicbytebBuffer;
}
[StructLayout(LayoutKind.Sequential,Pack=1)]
internalstructDriverStatus
{
publicbytebDriverError;
publicbytebIDEStatus;
[MarshalAs(UnmanagedType.ByValArray,SizeConst=2)]
publicbyte[]bReserved;
[MarshalAs(UnmanagedType.ByValArray,SizeConst=2)]
publicuint[]dwReserved;
}
[StructLayout(LayoutKind.Sequential,Pack=1)]
internalstructSendCmdOutParams
{
publicuintcBufferSize;
publicDriverStatusDriverStatus;
publicIdSectorbBuffer;
}
[StructLayout(LayoutKind.Sequential,Pack=1,Size=512)]
internalstructIdSector
{
publicushortwGenConfig;
publicushortwNumCyls;
publicushortwReserved;
publicushortwNumHeads;
publicushortwBytesPerTrack;
publicushortwBytesPerSector;
publicushortwSectorsPerTrack;
[MarshalAs(UnmanagedType.ByValArray,SizeConst=3)]
publicushort[]wVendorUnique;
[MarshalAs(UnmanagedType.ByValArray,SizeConst=20)]
publicbyte[]sSerialNumber;
publicushortwBufferType;
publicushortwBufferSize;
publicushortwECCSize;
[MarshalAs(UnmanagedType.ByValArray,SizeConst=8)]
publicbyte[]sFirmwareRev;
[MarshalAs(UnmanagedType.ByValArray,SizeConst=40)]
publicbyte[]sModelNumber;
publicushortwMoreVendorUnique;
publicushortwDoubleWordIO;
publicushortwCapabilities;
publicushortwReserved1;
publicushortwPIOTiming;
publicushortwDMATiming;
publicushortwBS;
publicushortwNumCurrentCyls;
publicushortwNumCurrentHeads;
publicushortwNumCurrentSectorsPerTrack;
publicuintulCurrentSectorCapacity;
publicushortwMultSectorStuff;
publicuintulTotalAddressableSectors;
publicushortwSingleWordDMA;
publicushortwMultiWordDMA;
[MarshalAs(UnmanagedType.ByValArray,SizeConst=128)]
publicbyte[]bReserved;
}
#endregion
///
///ATAPI驱动器相关
///
publicclassAtapiDevice
{
#regionDllImport
[DllImport("kernel32.dll",SetLastError=true)]
staticexternintCloseHandle(IntPtrhObject);
[DllImport("kernel32.dll",SetLastError=true)]
staticexternIntPtrCreateFile(
stringlpFileName,
uintdwDesiredAccess,
uintdwShareMode,
IntPtrlpSecurityAttributes,
uintdwCreationDisposition,
uintdwFlagsAndAttributes,
IntPtrhTemplateFile);
[DllImport("kernel32.dll")]
staticexternintDeviceIoControl(
IntPtrhDevice,
uintdwIoControlCode,
IntPtrlpInBuffer,
uintnInBufferSize,
refGetVersionOutParamslpOutBuffer,
uintnOutBufferSize,
refuintlpBytesReturned,
[Out]IntPtrlpOverlapped);
[DllImport("kernel32.dll")]
staticexternintDeviceIoControl(
IntPtrhDevice,
uintdwIoControlCode,
refSendCmdInParamslpInBuffer,
uintnInBufferSize,
refSendCmdOutParamslpOutBuffer,
uintnOutBufferSize,
refuintlpBytesReturned,
[Out]IntPtrlpOverlapped);
constuintDFP_GET_VERSION=0x00074080;
constuintDFP_SEND_DRIVE_COMMAND=0x0007c084;
constuintDFP_RECEIVE_DRIVE_DATA=0x0007c088;
constuintGENERIC_READ=0x80000000;
constuintGENERIC_WRITE=0x40000000;
constuintFILE_SHARE_READ=0x00000001;
constuintFILE_SHARE_WRITE=0x00000002;
constuintCREATE_NEW=1;
constuintOPEN_EXISTING=3;
#endregion
#regionGetHddInfo
///
///获得硬盘信息
///
///硬盘序号
///硬盘信息
///
///参考lu0的文章:
http:
//lu0s1.3322.org/App/2k1103.html
///bysunmastforeveryone
///thankslu0forhisgreatworks
///在Windows98/ME中,S.M.A.R.T并不缺省安装,请将SMARTVSD.VXD拷贝到%SYSTEM%\IOSUBSYS目录下。
///在Windows2000/2003下,需要Administrators组的权限。
///
///
///AtapiDevice.GetHddInfo()
///
publicstaticHardDiskInfoGetHddInfo(bytedriveIndex)
{
switch(Environment.OSVersion.Platform)
{
casePlatformID.Win32Windows:
returnGetHddInfo9x(driveIndex);
casePlatformID.Win32NT:
returnGetHddInfoNT(driveIndex);
casePlatformID.Win32S:
thrownewNotSupportedException("Win32sisnotsupported.");
casePlatformID.WinCE:
thrownewNotSupportedException("WinCEisnotsupported.");
default:
thrownewNotSupportedException("UnknownPlatform.");
}
}
#regionGetHddInfo9x
privatestaticHardDiskInfoGetHddInfo9x(bytedriveIndex)
{
GetVersionOutParamsvers=newGetVersionOutParams();
SendCmdInP