几种读取硬盘序列号的方法

<![CDATA[

  • 使用WMI的方法 <div


    using System.Management;
    ManagementClass mc
    =new ManagementClass(Win32_PhysicalMedia);
    foreach(ManagementObject mb in aa.GetInstances())
    {
    MessageBox.Show(
    bb.Properties[
    SerialNumber].Value.Tostring();
    }



  • 使用API的方法,这是从网上找到的,可以编译,但运行时有异常,因为是VB的,没有搞定

    Option Strict On
    Option Explicit On
    Imports System.Runtime.InteropServices
    Public Class DriveInfo
    Public Enum DriveTypes
    Fixed
    Removable
    Unknown
    End Enum

    Private _serialNumber As String
    Private _model As String
    Private _firmware As String
    Private _driveType As DriveTypes = DriveTypes.Unknown
    Private _numberCylinders As Integer
    Private _numberHeads As Integer
    Private _sectorsPerTrack As Integer
    Private _bufferSize As Integer
    #Region
    Win32 Interop”
    Private Class IDEREGS
    Public Features As Byte
    Public SectorCount As Byte
    Public SectorNumber As Byte
    Public CylinderLow As Byte
    Public CylinderHigh As Byte
    Public DriveHead As Byte
    Public Command As Byte
    Public Reserved As Byte
    End Class

    Private Class SENDCMDINPARAMS
    Public BufferSize As Integer
    Public DriveRegs As IDEREGS
    Public DriveNumber As Byte
    Public Reserved() As Byte
    Public Reserved2() As Integer
    Public Sub New()
    DriveRegs
    = New IDEREGS
    Reserved
    = New Byte(2) {}
    Reserved2
    = New Integer(3) {}
    End Sub

    End Class

    Private Class DRIVERSTATUS
    Public DriveError As Byte
    Public IDEStatus As Byte
    Public Reserved() As Byte
    Public Reserved2() As Integer
    Public Sub New()
    Reserved
    = New Byte(1) {}
    Reserved2
    = New Integer(1) {}
    End Sub

    End Class

    Private Class IDSECTOR
    Public GenConfig As Short 0
    Public NumberCylinders As Short 1
    Public Reserved As Short 2
    Public NumberHeads As Short 3
    Public BytesPerTrack As Short 4
    Public BytesPerSector As Short 5
    Public SectorsPerTrack As Short 6
    Public VendorUnique() As Short 7
    Public SerialNumber() As Char 10
    Public BufferClass As Short 20
    Public BufferSize As Short 21
    Public ECCSize As Short 22
    Public FirmwareRevision() As Char 23
    Public ModelNumber() As Char 27
    Public MoreVendorUnique As Short 47
    Public DoubleWordIO As Short 48
    Public Capabilities As Short 49
    Public Reserved1 As Short 50
    Public PIOTiming As Short 51
    Public DMATiming As Short 52
    Public BS As Short 53
    Public NumberCurrentCyls As Short 54
    Public NumberCurrentHeads As Short 55
    Public NumberCurrentSectorsPerTrack As Short 56
    Public CurrentSectorCapacity As Integer 57
    Public MultipleSectorCapacity As Short 59
    Public MultipleSectorStuff As Short 60
    Public TotalAddressableSectors As Integer 61
    Public SingleWordDMA As Short 63
    Public MultiWordDMA As Short 64
    Public Reserved2() As Byte 65
    Public Sub New()
    VendorUnique
    = New Short(2) {}
    Reserved2
    = New Byte(381) {}
    FirmwareRevision
    = New Char(7) {}
    SerialNumber
    = New Char(19) {}
    ModelNumber
    = New Char(39) {}
    End Sub

    End Class

    Private Class SENDCMDOUTPARAMS
    Public BufferSize As Integer
    Public Status As DRIVERSTATUS
    Public IDS As IDSECTOR
    Public Sub New()
    Status
    = New DRIVERSTATUS
    IDS
    = New IDSECTOR
    End Sub

    End Class

    Private Declare Function CloseHandle Lib kernel32 (ByVal hObject As Integer) As Integer
    Private Declare Function CreateFile Lib kernel32 Alias CreateFileA (ByVal lpFileName As String, ByVal dwDesiredAccess As Integer, ByVal dwShareMode As Integer, ByVal lpSecurityAttributes As Integer, ByVal dwCreationDisposition As Integer, ByVal dwFlagsAndAttributes As Integer, ByVal hTemplateFile As Integer) As Integer
    Private Declare Function DeviceIoControl Lib kernel32 (ByVal hDevice As Integer, ByVal dwIoControlCode As Integer, <In, Out()> ByVal lpInBuffer As SENDCMDINPARAMS, ByVal nInBufferSize As Integer, <In, Out()> ByVal lpOutBuffer As SENDCMDOUTPARAMS, ByVal nOutBufferSize As Integer, ByRef lpBytesReturned As Integer, ByVal lpOverlapped As Integer) As Integer
    Private Const CREATE_NEW As Integer = 1
    Private Const OPEN_EXISTING As Integer = 3
    Private Const GENERIC_READ As Integer = &H80000000
    Private Const GENERIC_WRITE As Integer = &H40000000
    Private Const FILE_SHARE_READ As Integer = &H1
    Private Const FILE_SHARE_WRITE As Integer = &H2
    Private Const VER_PLATFORM_WIN32_NT As Integer = 2
    Private Const DFP_RECEIVE_DRIVE_DATA As Integer = &H7C088
    Private Const IOCTL_STORAGE_MEDIA_REMOVAL As Long = &H2D4804
    Private Const INVALID_HANDLE_VALUE As Integer = -1
    Private Shared Function SwapChars(ByVal chars() As Char) As String
    For i As Integer = 0 To chars.Length - 2 Step 2
    chars.Reverse(chars, i,
    2)
    Next
    Return New String(chars).Trim
    End Function

    #
    End Region

    Public Sub New(ByVal driveNumber As Integer)
    Dim result As Boolean
    Dim handle As Integer
    Dim returnSize As Integer
    Dim sci As New SENDCMDINPARAMS
    Dim sco As New SENDCMDOUTPARAMS
    If Environment.OSVersion.Platform = PlatformID.Win32NT Then
    handle = CreateFile(“\.\PhysicalDrive” & CStr(driveNumber), GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0)
    handle = CreateFile(\.\PhysicalDrive & CStr(driveNumber), GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0)
    handle = CreateFile(“\.\PhysicalDrive”, GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0)
    Else 9X
    handle = CreateFile(\.\Smartvsd, 0, 0, 0, CREATE_NEW, 0, 0)
    End If
    If handle <> INVALID_HANDLE_VALUE Then
    sci.DriveNumber
    = CType(driveNumber, Byte)
    sci.BufferSize
    = Marshal.SizeOf(sco)
    sci.DriveRegs.DriveHead
    = CType(&HA0 Or (driveNumber << 5), Byte)
    sci.DriveRegs.
    Command = &HEC
    sci.DriveRegs.SectorCount
    = 1
    sci.DriveRegs.SectorNumber
    = 1
    If DeviceIoControl(handle, DFP_RECEIVE_DRIVE_DATA, sci, Marshal.SizeOf(sci), sco, Marshal.SizeOf(sco), returnSize, 0) <> 0 Then
    _serialNumber
    = SwapChars(sco.IDS.SerialNumber)
    _model
    = SwapChars(sco.IDS.ModelNumber)
    _firmware
    = SwapChars(sco.IDS.FirmwareRevision)
    _numberCylinders
    = sco.IDS.NumberCylinders
    _numberHeads
    = sco.IDS.NumberHeads
    _sectorsPerTrack
    = sco.IDS.SectorsPerTrack
    _bufferSize
    = sco.IDS.BufferSize * 512
    If (sco.IDS.GenConfig And &H80) = &H80 Then
    _driveType
    = DriveTypes.Removable
    ElseIf (sco.IDS.GenConfig And &H40) = &H40 Then
    _driveType
    = DriveTypes.Fixed
    Else
    _driveType
    = DriveTypes.Unknown
    End If
    End If
    CloseHandle(handle)
    End If
    End Sub

    Public ReadOnly Property SerialNumber() As String
    Get
    Return _serialNumber
    End Get
    End Property

    Public ReadOnly Property Model() As String
    Get
    Return _model
    End Get
    End Property

    Public ReadOnly Property Firmware() As String
    Get
    Return _firmware
    End Get
    End Property

    Public ReadOnly Property NumberCylinders() As Integer
    Get
    Return _numberCylinders
    End Get
    End Property

    Public ReadOnly Property NumberHeads() As Integer
    Get
    Return _numberHeads
    End Get
    End Property

    Public ReadOnly Property SectorsPerTrack() As Integer
    Get
    Return _sectorsPerTrack
    End Get
    End Property

    Public ReadOnly Property BufferSize() As Integer
    Get
    Return _bufferSize
    End Get
    End Property

    Public ReadOnly Property DriveType() As DriveTypes
    Get
    Return _driveType
    End Get
    End Property

    End Class

    Class DriveInfoApp
    Shared Sub Main()
    For drive As Integer = 0 To 4
    Dim info As New DriveInfo(drive)
    If Not info.SerialNumber Is Nothing Then
    Select Case drive
    Case 0 : Console.WriteLine(Primary Controller - Master drive)
    Case 1 : Console.WriteLine(Primary Controller - Slave drive)
    Case 2 : Console.WriteLine(Secondary Controller - Master drive)
    Case 3 : Console.WriteLine(Secondary Controller - Slave drive)
    End Select
    Console.
    WriteLine()
    Console.
    WriteLine(Drive Model Number__: & info.Model)
    Console.
    WriteLine(Drive Serial Number___: & info.SerialNumber)
    Console.
    WriteLine(Drive Controller Revision Number: & info.Firmware)
    Console.
    WriteLine(Controller Buffer Size on Drive_: & info.BufferSize)
    Console.
    WriteLine(Drive Type__: & info.DriveType.ToString)
    Console.
    Write(Physical Geometry: )
    Console.
    Write(info.NumberCylinders & Cylinders )
    Console.
    Write(info.NumberHeads & Heads )
    Console.
    WriteLine(info.SectorsPerTrack & Sectors per track)
    Console.
    WriteLine()
    End If
    Next
    Console.ReadLine()
    End Sub

    End Class


  • 使用读取RING3的方法。这种方法没有办法用C#实现,起码我不知道,下面别人写的C++的方法

    /+++
    HDID.CPP
    Written by Lu Lin
    http://lu0.126.com
    2000.11.3
    /

    #include
    <windows.h>
    #include
    <iostream.h>
    #include
    <stdio.h>

    #define DFP_GET_VERSION 0x00074080
    #define DFP_SEND_DRIVE_COMMAND 0x0007c084
    #define DFP_RECEIVE_DRIVE_DATA 0x0007c088

    #pragma pack(
    1)
    typedef
    struct _GETVERSIONOUTPARAMS {
    BYTE bVersion;
    // Binary driver version.
    BYTE bRevision; // Binary driver revision.
    BYTE bReserved; // Not used.
    BYTE bIDEDeviceMap; // Bit map of IDE devices.
    DWORD fCapabilities; // Bit mask of driver capabilities.
    DWORD dwReserved[4]; // For future use.
    }
    GETVERSIONOUTPARAMS, PGETVERSIONOUTPARAMS, LPGETVERSIONOUTPARAMS;

    typedef
    struct _IDEREGS {
    BYTE bFeaturesReg;
    // Used for specifying SMART “commands”.
    BYTE bSectorCountReg; // IDE sector count register
    BYTE bSectorNumberReg; // IDE sector number register
    BYTE bCylLowReg; // IDE low order cylinder value
    BYTE bCylHighReg; // IDE high order cylinder value
    BYTE bDriveHeadReg; // IDE drive/head register
    BYTE bCommandReg; // Actual IDE command.
    BYTE bReserved; // reserved for future use. Must be zero.
    }
    IDEREGS, PIDEREGS, LPIDEREGS;

    typedef
    struct _SENDCMDINPARAMS {
    DWORD cBufferSize;
    // Buffer size in bytes
    IDEREGS irDriveRegs; // Structure with drive register values.
    BYTE bDriveNumber; // Physical drive number to send
    // command to (0,1,2,3).
    BYTE bReserved[3]; // Reserved for future expansion.
    DWORD dwReserved[4]; // For future use.
    //BYTE bBuffer[1]; // Input buffer.
    }
    SENDCMDINPARAMS, PSENDCMDINPARAMS, LPSENDCMDINPARAMS;

    typedef
    struct _DRIVERSTATUS {
    BYTE bDriverError;
    // Error code from driver,
    // or 0 if no error.
    BYTE bIDEStatus; // Contents of IDE Error register.
    // Only valid when bDriverError
    // is SMART_IDE_ERROR.
    BYTE bReserved[2]; // Reserved for future expansion.
    DWORD dwReserved[2]; // Reserved for future expansion.
    }
    DRIVERSTATUS, PDRIVERSTATUS, LPDRIVERSTATUS;

    typedef
    struct _SENDCMDOUTPARAMS {
    DWORD cBufferSize;
    // Size of bBuffer in bytes
    DRIVERSTATUS DriverStatus; // Driver status structure.
    BYTE bBuffer[512]; // Buffer of arbitrary length
    // in which to store the data read from the drive.
    }
    SENDCMDOUTPARAMS, PSENDCMDOUTPARAMS, LPSENDCMDOUTPARAMS;

    typedef
    struct _IDSECTOR {
    USHORT wGenConfig;
    USHORT wNumCyls;
    USHORT wReserved;
    USHORT wNumHeads;
    USHORT wBytesPerTrack;
    USHORT wBytesPerSector;
    USHORT wSectorsPerTrack;
    USHORT wVendorUnique[
    3];
    CHAR sSerialNumber[
    20];
    USHORT wBufferType;
    USHORT wBufferSize;
    USHORT wECCSize;
    CHAR sFirmwareRev[
    8];
    CHAR sModelNumber[
    40];
    USHORT wMoreVendorUnique;
    USHORT wDoubleWordIO;
    USHORT wCapabilities;
    USHORT wReserved1;
    USHORT wPIOTiming;
    USHORT wDMATiming;
    USHORT wBS;
    USHORT wNumCurrentCyls;
    USHORT wNumCurrentHeads;
    USHORT wNumCurrentSectorsPerTrack;
    ULONG ulCurrentSectorCapacity;
    USHORT wMultSectorStuff;
    ULONG ulTotalAddressableSectors;
    USHORT wSingleWordDMA;
    USHORT wMultiWordDMA;
    BYTE bReserved[
    128];
    }
    IDSECTOR, *PIDSECTOR;

    /+++
    Global vars
    /

    GETVERSIONOUTPARAMS vers;
    SENDCMDINPARAMS
    in;
    SENDCMDOUTPARAMS
    out;
    HANDLE h;
    DWORD i;
    BYTE j;

    void CopyRight(){
    cerr
    <<endl<<HDD identifier v1.0 for WIN95/98/Me/NT/2000. written by Lu Lin<<endl;
    cerr
    <<For more information, please visit Inside Programming: http://lu0.126.com<<endl;
    cerr
    <<2000.11.3<<endl<<endl;
    }

    VOID ChangeByteOrder(PCHAR szString, USHORT uscStrSize)
    {

    USHORT i;
    CHAR temp;

    for (i = 0; i < uscStrSize; i+=2)
    {
    temp
    = szString[i];
    szString[i]
    = szString[i+1];
    szString[i
    +1] = temp;
    }

    }


    void DetectIDE(BYTE bIDEDeviceMap){
    if (bIDEDeviceMap&1){
    if (bIDEDeviceMap&16){
    cout
    <<ATAPI device is attached to primary controller, drive 0.<<endl;
    }
    else{
    cout
    <<IDE device is attached to primary controller, drive 0.<<endl;
    }

    }

    if (bIDEDeviceMap&2){
    if (bIDEDeviceMap&32){
    cout
    <<ATAPI device is attached to primary controller, drive 1.<<endl;
    }
    else{
    cout
    <<IDE device is attached to primary controller, drive 1.<<endl;
    }

    }

    if (bIDEDeviceMap&4){
    if (bIDEDeviceMap&64){
    cout
    <<ATAPI device is attached to secondary controller, drive 0.<<endl;
    }
    else{
    cout
    <<IDE device is attached to secondary controller, drive 0.<<endl;
    }

    }

    if (bIDEDeviceMap&8){
    if (bIDEDeviceMap&128){
    cout
    <<ATAPI device is attached to secondary controller, drive 1.<<endl;
    }
    else{
    cout
    <<IDE device is attached to secondary controller, drive 1.<<endl;
    }

    }

    }


    void hdid9x(){
    ZeroMemory(
    &vers,sizeof(vers));
    //We start in 95/98/Me
    h=CreateFile(\\.\Smartvsd,0,0,0,CREATE_NEW,0,0);
    if (!h){
    cout
    <<open smartvsd.vxd failed<<endl;
    exit(
    0);
    }


    if (!DeviceIoControl(h,DFP_GET_VERSION,0,0,&vers,sizeof(vers),&i,0)){
    cout
    <<DeviceIoControl failed:DFP_GET_VERSION<<endl;
    CloseHandle(h);
    return;
    }

    //If IDE identify command not supported, fails
    if (!(vers.fCapabilities&1)){
    cout
    <<Error: IDE identify command not supported.;
    CloseHandle(h);
    return;
    }

    //Display IDE drive number detected
    DetectIDE(vers.bIDEDeviceMap);
    //Identify the IDE drives
    for (j=0;j<4;j++){
    PIDSECTOR phdinfo;
    char s[41];

    ZeroMemory(
    &in,sizeof(in));
    ZeroMemory(
    &out,sizeof(out));
    if (j&1){
    in.irDriveRegs.bDriveHeadReg=0xb0;
    }
    else{
    in.irDriveRegs.bDriveHeadReg=0xa0;
    }

    if (vers.fCapabilities&(16>>j)){
    //We don’t detect a ATAPI device.
    cout<<Drive <<(int)(j+1)<< is a ATAPI device, we don’t detect it<<endl;
    continue;
    }
    else{
    in.irDriveRegs.bCommandReg=0xec;
    }

    in.bDriveNumber=j;
    in.irDriveRegs.bSectorCountReg=1;
    in.irDriveRegs.bSectorNumberReg=1;
    in.cBufferSize=512;
    if (!DeviceIoControl(h,DFP_RECEIVE_DRIVE_DATA,&in,sizeof(in),&out,sizeof(out),&i,0)){
    cout
    <<DeviceIoControl failed:DFP_RECEIVE_DRIVE_DATA<<endl;
    CloseHandle(h);
    return;
    }

    phdinfo
    =(PIDSECTOR)out.bBuffer;
    memcpy(s,phdinfo
    ->sModelNumber,40);
    s[
    40]=0;
    ChangeByteOrder(s,
    40);
    cout
    <<endl<<Module Number:<<s<<endl;
    memcpy(s,phdinfo
    ->sFirmwareRev,8);
    s[
    8]=0;
    ChangeByteOrder(s,
    8);
    cout
    <<\tFirmware rev:<<s<<endl;
    memcpy(s,phdinfo
    ->sSerialNumber,20);
    s[
    20]=0;
    ChangeByteOrder(s,
    20);
    cout
    <<\tSerial Number:<<s<<endl;
    cout
    <<\tCapacity:<<phdinfo->ulTotalAddressableSectors/2/1024<<M<<endl<<endl;
    }


    //Close handle before quit
    CloseHandle(h);
    CopyRight();

    }


    void hdidnt(){
    char hd[80];
    PIDSECTOR phdinfo;
    char s[41];

    ZeroMemory(
    &vers,sizeof(vers));
    //We start in NT/Win2000
    for (j=0;j<4;j++){
    sprintf(hd,
    \\.\PhysicalDrive%d,j);
    h
    =CreateFile(hd,GENERIC_READ|GENERIC_WRITE,
    FILE_SHARE_READ
    |FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0);
    if (!h){
    continue;
    }

    if (!DeviceIoControl(h,DFP_GET_VERSION,0,0,&vers,sizeof(vers),&i,0)){
    CloseHandle(h);
    continue;
    }

    //If IDE identify command not supported, fails
    if (!(vers.fCapabilities&1)){
    cout
    <<Error: IDE identify command not supported.;
    CloseHandle(h);
    return;
    }

    //Identify the IDE drives
    ZeroMemory(&in,sizeof(in));
    ZeroMemory(
    &out,sizeof(out));
    if (j&1){
    in.irDriveRegs.bDriveHeadReg=0xb0;
    }
    else{
    in.irDriveRegs.bDriveHeadReg=0xa0;
    }

    if (vers.fCapabilities&(16>>j)){
    //We don’t detect a ATAPI device.
    cout<<Drive <<(int)(j+1)<< is a ATAPI device, we don’t detect it<<endl;
    continue;
    }
    else{
    in.irDriveRegs.bCommandReg=0xec;
    }

    in.bDriveNumber=j;
    in.irDriveRegs.bSectorCountReg=1;
    in.irDriveRegs.bSectorNumberReg=1;
    in.cBufferSize=512;
    if (!DeviceIoControl(h,DFP_RECEIVE_DRIVE_DATA,&in,sizeof(in),&out,sizeof(out),&i,0)){
    cout
    <<DeviceIoControl failed:DFP_RECEIVE_DRIVE_DATA<<endl;
    CloseHandle(h);
    return;
    }

    phdinfo
    =(PIDSECTOR)out.bBuffer;
    memcpy(s,phdinfo
    ->sModelNumber,40);
    s[
    40]=0;
    ChangeByteOrder(s,
    40);
    cout
    <<endl<<Module Number:<<s<<endl;
    memcpy(s,phdinfo
    ->sFirmwareRev,8);
    s[
    8]=0;
    ChangeByteOrder(s,
    8);
    cout
    <<\tFirmware rev:<<s<<endl;
    memcpy(s,phdinfo
    ->sSerialNumber,20);
    s[
    20]=0;
    ChangeByteOrder(s,
    20);
    cout
    <<\tSerial Number:<<s<<endl;
    cout
    <<\tCapacity:<<phdinfo->ulTotalAddressableSectors/2/1024<<M<<endl<<endl;
    CloseHandle(h);
    }

    CopyRight();
    }


    void main(){
    OSVERSIONINFO VersionInfo;

    ZeroMemory(
    &VersionInfo,sizeof(VersionInfo));
    VersionInfo.dwOSVersionInfoSize
    =sizeof(VersionInfo);
    GetVersionEx(
    &VersionInfo);

    switch (VersionInfo.dwPlatformId){
    case VER_PLATFORM_WIN32s:
    cout
    <<Win32s is not supported by this programm.<<endl;
    return;
    case VER_PLATFORM_WIN32_WINDOWS:
    hdid9x();
    return;
    case VER_PLATFORM_WIN32_NT:
    hdidnt();
    return;
    }

    }




    还有以下疑问:
    1. C#中如何通过上文API的方法来读取硬盘序列号
    2. win98不支持WMI,那为什么在.net frameowork SDK中说,
    ManagementClass.GetInstances()和ManagementClass.Get()都
    可以在win98平台运行
    ]]>