遗憾的是很多朋友往往分不清这一点。
要得到硬盘的物理序列号,可以通过WMI,也就是Win32_PhysicalMedia.SerialNumber。
可惜的是Windows98/ME的WMI并不支持这个类,访问时会出现异常。
受陆麟的例子的启发,我们还可以通过S.M.A.R.T.接口,直接从RING3调用APIDeviceIoControl(>来获取硬盘信息,而不需要写VXD或者DRIVER。
这样这个问题就解决了,我对它进行了封装,大量使用了P/Invoke技术,一个完整的Library。
支持Windows98-2003。
b5E2RGbCAP
使用上很简单:
HardDiskInfohdd=AtapiDevice.GetHddInfo(0>。
//第一个硬盘p1EanqFDPw
Console.WriteLine("ModuleNumber:
{0}",hdd.ModuleNumber>。
DXDiTa9E3d
Console.WriteLine("SerialNumber:
{0}",hdd.SerialNumber>。
RTCrpUDGiT
Console.WriteLine("Firmware:
{0}",hdd.Firmware>。
Console.WriteLine("Capacity:
{0}M",hdd.Capacity>。
5PCzVD7HxA
下面是全部代码:
usingSystem。
usingSystem.Runtime.InteropServices。
usingSystem.Text。
namespaceSunmast.Hardware
{
[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>]jLBHrnAILg
internalstructIdSector
{
publicushortwGenConfig。
publicushortwNumCyls。
publicushortwReserved。
publicushortwNumHeads。
publicushortwBytesPerTrack。
publicushortwBytesPerSector。
publicushortwSectorsPerTrack。
[MarshalAs(UnmanagedType.ByValArray,SizeConst=3>]
publicushort[]wVendorUnique。
[MarshalAs(UnmanagedType.ByValArray,SizeConst=20>]xHAQX74J0X
publicbyte[]sSerialNumber。
publicushortwBufferType。
publicushortwBufferSize。
publicushortwECCSize。
[MarshalAs(UnmanagedType.ByValArray,SizeConst=8>]
publicbyte[]sFirmwareRev。
[MarshalAs(UnmanagedType.ByValArray,SizeConst=40>]LDAYtRyKfE
publicbyte[]sModelNumber。
publicushortwMoreVendorUnique。
publicushortwDoubleWordIO。
publicushortwCapabilities。
publicushortwReserved1。
publicushortwPIOTiming。
publicushortwDMATiming。
publicushortwBS。
publicushortwNumCurrentCyls。
publicushortwNumCurrentHeads。
publicushortwNumCurrentSectorsPerTrack。
publicuintulCurrentSectorCapacity。
publicushortwMultSectorStuff。
publicuintulTotalAddressableSectors。
publicushortwSingleWordDMA。
publicushortwMultiWordDMA。
[MarshalAs(UnmanagedType.ByValArray,SizeConst=128>]Zzz6ZB2Ltk
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目录下。
dvzfvkwMI1
///在Windows2000/2003下,需要Administrators组的权限。
///
///
///AtapiDevice.GetHddInfo(>
///
publicstaticHardDiskInfoGetHddInfo(bytedriveIndex>rqyn14ZNXI
{
switch(Environment.OSVersion.Platform>
{
casePlatformID.Win32Windows:
returnGetHddInfo9x(driveIndex>。
casePlatformID.Win32NT:
returnGetHddInfoNT(driveIndex>。
casePlatformID.Win32S:
thrownewNotSupportedException("Win32sisnotsupported.">。
EmxvxOtOco
casePlatformID.WinCE:
thrownewNotSupportedException("WinCEisnotsupported.">。
SixE2yXPq5
default:
thrownewNotSupportedException("UnknownPlatform.">。
6ewMyirQFL
}
}
#regionGetHddInfo9x
privatestaticHardDiskInfoGetHddInfo9x(bytedriveIndex>kavU42VRUs
{
GetVersionOutParamsvers=newGetVersionOutParams(>。
y6v3ALoS89
SendCmdInParamsinParam=newSendCmdInParams(>。
SendCmdOutParamsoutParam=newSendCmdOutParams(>。
M2ub6vSTnP
uintbytesReturned=0。
IntPtrhDevice=CreateFile(
@"\\.\Smartvsd",
0,
0,
IntPtr.Zero,
CREATE_NEW,
0,
IntPtr.Zero>。
if(hDevice==IntPtr.Zero>
{
thrownewException("Opensmartvsd.vxdfailed.">。
}
if(0==DeviceIoControl(
hDevice,
DFP_GET_VERSION,
IntPtr.Zero,
0,
refvers,
(uint>Marshal.SizeOf(vers>,
refbytesReturned,
IntPtr.Zero>>
{
CloseHandle(hDevice>。
thrownewException("DeviceIoControlfailed:
DFP_GET_VERSION">。
0YujCfmUCw
}
//IfIDEidentifycommandnotsupported,fails
if(0==(vers.fCapabilities&1>>
{
CloseHandle(hDevice>。
thrownewException("Error:
IDEidentifycommandnotsupported.">。
eUts8ZQVRd
}
if(0!
=(driveIndex&1>>
{
inParam.irDriveRegs.bDriveHeadReg=0xb0。
}
else
{
inParam.irDriveRegs.bDriveHeadReg=0xa0。
}
if(0!
=(vers.fCapabilities&(16>>driveIndex>>>sQsAEJkW5T
{
//Wedon''tdetectaATAPIdevice.
CloseHandle(hDevice>。
thrownewException(string.Format("Drive{0}isaATAPIdevice,wedon''tdetectit",driveIndex+1>>。
GMsIasNXkA
}
else
{
inParam.irDriveRegs.bCommandReg=0xec。
}
inParam.bDriveNumber=driveIndex。
inParam.irDriveRegs.bSectorCountReg=1。
inParam.irDriveRegs.bSectorNumberReg=1。
inParam.cBufferSize=512。
if(0==DeviceIoControl(
hDevice,
DFP_RECEIVE_DRIVE_DATA,
refinParam,
(uint>Marshal.SizeOf(inParam>,
refoutParam,
(uint>Marshal.SizeOf(outParam>,
refbytesReturned,
IntPtr.Zero>>
{
CloseHandle(hDevice>。
thrownewException("DeviceIoControlfailed:
DFP_RECEIVE_DRIVE_DATA">。
TIrRGchYzg
}
CloseHandle(hDevice>。
returnGetHardDiskInfo(outParam.bBuffer>。
}
#endregion
#regionGetHddInfoNT
privatestaticHardDiskInfoGetHddInfoNT(bytedriveIndex>7EqZcWLZNX
{
GetVersionOutParamsvers=newGetVersionOutParams(>。
lzq7IGf02E
SendCmdInParamsinParam=newSendCmdInParams(>。
SendCmdOutParamsoutParam=newSendCmdOutParams(>。
zvpgeqJ1hk
uintbytesReturned=0。
//WestartinNT/Win2000
IntPtrhDevice=CreateFile(
string.Format(@"\\.\PhysicalDrive{0}",driveIndex>,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
IntPtr.Zero,
OPEN_EXISTING,
0,
IntPtr.Zero>。
if(hDevice==IntPtr.Zero>
{
thrownewException("CreateFilefaild.">。
}
if(0==DeviceIoControl(
hDevice,
DFP_GET_VERSION,
IntPtr.Zero,
0,
refvers,
(uint>Marshal.SizeOf(vers>,
refbytesReturned,
IntPtr.Zero>>
{
CloseHandle(hDevice>。
thrownewException(string.Format("Drive{0}maynotexists.",driveIndex+1>>。
NrpoJac3v1
}
//IfIDEidentifycommandnotsupported,fails
if(0==(vers.fCapabilities&1>>
{
CloseHandle(hDevice>。
thrownewException("Error:
IDEidentifycommandnotsupported.">。
1nowfTG4KI
}
//IdentifytheIDEdrives
if(0!
=(driveIndex&1>>
{
inParam.irDriveRegs.bDriveHeadReg=0xb0。
}
else
{
inParam.irDriveRegs.bDriveHeadReg=0xa0。
}
if(0!
=(vers.fCapabilities&(16>>driveIndex>>>fjnFLDa5Zo
{
//Wedon''tdetectaATAPIdevice.
CloseHandle(hDevice>。
thrownewException(string.Format("Drive{0}isaATAPIdevice,wedon''tdetectit.",driveIndex+1>>。
tfnNhnE6e5
}
else
{
inParam.irDriveRegs.bCommandReg=0xec。
}
inParam.bDriveNumber=driveIndex。
inParam.irDriveRegs.bSectorCountReg=1。
inParam.irDriveRegs.bSectorNumberReg=1。
inParam.cBufferSize=512。
if(0==DeviceIoControl(
hDevice,
DFP_RECEIVE_DRIVE_DATA,
refinParam,
(uint>Marshal.SizeOf(inParam>,
refoutParam,
(uint>Marshal.SizeOf(outParam>,
refbytesR