HOW TO:获取硬盘物理序列号,VB.NET

Author:水如烟

参考了一个C#的,原出处不知在哪了.

Public Class PhysicalDriveDemo

Public Shared Sub Run()

Console.WriteLine(PhysicalDrive.GetSerialNumber(0))

End Sub

End Class

Imports System

Imports System.Collections.Generic

Imports System.Text

Imports System.Runtime.InteropServices

Public Class PhysicalDrive

'<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _

' Friend Structure IDSECTOR

' Public wGenConfig As Int16

' Public wNumCyls As Int16

' Public wReserved As Int16

' Public wNumHeads As Int16

' Public wBytesPerTrack As Int16

' Public wBytesPerSector As Int16

' Public wSectorsPerTrack As Int16

' <MarshalAs(UnmanagedType.ByValArray, SizeConst:=3)> _

' Public wVendorUnique() As Int16

' <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=20)> _

' Public sSerialNumber As String

' Public wBufferType As Int16

' Public wBufferSize As Int16

' Public wECCSize As Int16

' <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=8)> _

' Public sFirmwareRev As String

' <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=40)> _

' Public sModelNumber As String

' Public wMoreVendorUnique As Int16

' Public wDoubleWordIO As Int16

' Public wCapabilities As Int16

' Public wReserved1 As Int16

' Public wPIOTiming As Int16

' Public wDMATiming As Int16

' Public wBS As Int16

' Public wNumCurrentCyls As Int16

' Public wNumCurrentHeads As Int16

' Public wNumCurrentSectorsPerTrack As Int16

' Public ulCurrentSectorCapacity As Int32

' Public wMultSectorStuff As Int16

' Public ulTotalAddressableSectors As Int32

' Public wSingleWordDMA As Int16

' Public wMultiWordDMA As Int16

' <MarshalAs(UnmanagedType.ByValArray, SizeConst:=128)> _

' Public bReserved() As Byte

'End Structure

<StructLayout(LayoutKind.Sequential)> _

Friend Structure DRIVERSTATUS

Public bDriverError As Byte

Public bIDEStatus As Byte

<MarshalAs(UnmanagedType.ByValArray, SizeConst:=2)> _

Public bReserved() As Byte

<MarshalAs(UnmanagedType.ByValArray, SizeConst:=2)> _

Public dwReserved() As Int32

End Structure

<StructLayout(LayoutKind.Sequential)> _

Friend Structure SENDCMDOUTPARAMS

Public cBufferSize As Int32

Public DriverStatus As DRIVERSTATUS

<MarshalAs(UnmanagedType.ByValArray, SizeConst:=513)> _

Public bBuffer() As Byte

End Structure

'<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _

' Friend Structure SRB_IO_CONTROL

' Public HeaderLength As Int32

' <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=8)> _

' Public Signature As String

' Public Timeout As Int32

' Public ControlCode As Int32

' Public ReturnCode As Int32

' Public Length As Int32

'End Structure

<StructLayout(LayoutKind.Sequential)> _

Friend Structure IDEREGS

Public bFeaturesReg As Byte

Public bSectorCountReg As Byte

Public bSectorNumberReg As Byte

Public bCylLowReg As Byte

Public bCylHighReg As Byte

Public bDriveHeadReg As Byte

Public bCommandReg As Byte

Public bReserved As Byte

End Structure

<StructLayout(LayoutKind.Sequential)> _

Friend Structure SENDCMDINPARAMS

Public cBufferSize As Int32

Public irDriveRegs As IDEREGS

Public bDriveNumber As Byte

<MarshalAs(UnmanagedType.ByValArray, SizeConst:=3)> _

Public bReserved() As Byte

<MarshalAs(UnmanagedType.ByValArray, SizeConst:=4)> _

Public dwReserved() As Int32

Public bBuffer As Byte

End Structure

<StructLayout(LayoutKind.Sequential)> _

Friend Structure GETVERSIONOUTPARAMS

Public bVersion As Byte

Public bRevision As Byte

Public bReserved As Byte

Public bIDEDeviceMap As Byte

Public fCapabilities As Int32

<MarshalAs(UnmanagedType.ByValArray, SizeConst:=4)> _

Public dwReserved() As Int32

End Structure

<DllImport("kernel32.dll", SetLastError:=True)> _

Private Shared Function CloseHandle( _

ByVal hObject As Int32 _

) As Integer

End Function

<DllImport("kernel32.dll")> _

Private Overloads Shared Function DeviceIoControl( _

ByVal hDevice As Int32, _

ByVal dwIoControlCode As Int32, _

ByRef lpInBuffer As SENDCMDINPARAMS, _

ByVal nInBufferSize As Integer, _

ByRef lpOutBuffer As SENDCMDOUTPARAMS, _

ByVal nOutBufferSize As Integer, _

ByRef lpbytesReturned As Int32, _

ByVal lpOverlapped As Integer _

) As Integer

End Function

<DllImport("kernel32.dll")> _

Private Overloads Shared Function DeviceIoControl( _

ByVal hDevice As Int32, _

ByVal dwIoControlCode As Int32, _

ByVal lpInBuffer As Integer, _

ByVal nInBufferSize As Integer, _

ByRef lpOutBuffer As GETVERSIONOUTPARAMS, _

ByVal nOutBufferSize As Integer, _

ByRef lpbytesReturned As Int32, _

ByVal lpOverlapped As Integer _

) As Integer

End Function

<DllImport("kernel32.dll")> _

Private Shared Function CreateFile( _

ByVal lpFileName As String, _

ByVal dwDesiredAccess As Int32, _

ByVal dwShareMode As Int32, _

ByVal lpSecurityAttributes As Integer, _

ByVal dwCreationDisposition As Int32, _

ByVal dwFlagsAndAttributes As Int32, _

ByVal hTemplateFile As Integer _

) As Int32

End Function

Private Const GENERIC_READ As Int32 = &H80000000

Private Const GENERIC_WRITE As Int32 = &H40000000

Private Const FILE_SHARE_READ As Int32 = &H1

Private Const FILE_SHARE_WRITE As Int32 = &H2

Private Const OPEN_EXISTING As Int32 = 3

Private Const INVALID_HANDLE_VALUE As Int32 = &HFFFFFFFF

Private Const DFP_GET_VERSION As Int32 = &H74080

Private Const IDE_ATAPI_IDENTIFY As Integer = &HA1

Private Const IDE_ATA_IDENTIFY As Integer = &HEC

Private Const IDENTIFY_BUFFER_SIZE As Integer = 512

Private Const DFP_RECEIVE_DRIVE_DATA As Int32 = &H7C088

''' <summary>

''' 获取物理序列号

''' </summary>

''' <param name="id">系统硬盘序号,0-255</param>

Public Shared Function GetSerialNumber(ByVal id As Byte) As String

Dim os As OperatingSystem = Environment.OSVersion

If os.Platform <> PlatformID.Win32NT Then

Throw New NotSupportedException("仅支持2000/XP/2003")

End If

If os.Version.Major < 5 Then

Throw New NotSupportedException("仅支持2000/XP/2003")

End If

Return Read(id)

End Function

Private Shared Function Read(ByVal drive As Byte) As String

Dim driveName As String = String.Concat("\\.\PhysicalDrive", drive.ToString())

Dim device As Int32 = CreateFile( _

driveName, _

GENERIC_READ Or GENERIC_WRITE, _

FILE_SHARE_READ Or FILE_SHARE_WRITE, _

0, _

OPEN_EXISTING, _

0, _

0)

If device = INVALID_HANDLE_VALUE Then

Return ""

End If

Dim verPara As New GETVERSIONOUTPARAMS()

Dim bytRv As Int32 = 0

If DeviceIoControl( _

device, _

DFP_GET_VERSION, _

0, _

0, _

verPara, _

Marshal.SizeOf(verPara), _

bytRv, _

0 _

) <> 0 Then

If verPara.bIDEDeviceMap > 0 Then

Dim bIDCmd As Byte = CByte(IIf((verPara.bIDEDeviceMap >> drive And &H10) <> 0, IDE_ATAPI_IDENTIFY, IDE_ATA_IDENTIFY))

Dim scip As New SENDCMDINPARAMS()

Dim scop As New SENDCMDOUTPARAMS()

With scip

.cBufferSize = IDENTIFY_BUFFER_SIZE

.bDriveNumber = drive

With .irDriveRegs

.bFeaturesReg = 0

.bSectorCountReg = 1

.bCylLowReg = 0

.bCylHighReg = 0

.bDriveHeadReg = CByte((&HA0 Or ((drive And 1) << 4)))

.bCommandReg = bIDCmd

End With

End With

If DeviceIoControl(device, DFP_RECEIVE_DRIVE_DATA, scip, Marshal.SizeOf(scip), scop, Marshal.SizeOf(scop), bytRv, 0) <> 0 Then

Dim s As New StringBuilder()

Dim i As Integer

For i = 20 To 40 - 2 Step 2

s.Append(ChrW(scop.bBuffer((i + 1))))

s.Append(ChrW(scop.bBuffer(i)))

Next i

CloseHandle(device)

Return s.ToString().Trim()

End If

End If

End If

CloseHandle(device)

Return ""

End Function

End Class

其它信息,可以参考:

Disk Serial Number'—Using the WMI Scripting Library