thongkorn โพสต์ 2019-1-27 16:12:07

[VB6] อ่านค่า Physical Serial Number ของฮาร์ดดิสต์ที่บู๊ตระบบวินโดวส์ด้วย API

http://www.g2gnet.com/webboard/images/vb6/getbootdiskapi.png


จากตอนที่แล้วได้นำเสนอ การค้นหา Harddisk ที่ติดตั้ง Windows พร้อมกับอ่านค่า Physical Serial Number ด้วย WMI (Windows Management Instrumentation) มาตอนนี้จะใช้ Win32 API หรือ Application Programming Interface ซึ่งค่อนข้างจะทำความเข้าใจในตัวโค้ดได้ยากมากกว่า WMI แต่ทว่ากลับได้ผลลัพธ์ที่ค่อนข้างจะเที่ยงตรงและแม่นยำ ในกรณีที่ฮาร์ดดิสต์ของคุณมีอยู่หลายลูก และติดตั้งระบบปฏิบัติการวินโดวส์เอาไว้หลายเวอร์ชั่น เรื่องแบบนี้ต้องลองทดสอบกันดูเอาเองครับ ... อนึ่ง!!! สำหรับในตอนนี้แอดมินเลือกใช้ API สำหรับการค้นหาว่าระบบปฏิบัติการมันถูกบู๊ตระบบจากไดร์ฟอะไร (เช่น C) และคืนค่ากลับให้เป็นหมายเลขของ Physical Harddisk แต่เวลาหา Serial Number แอดมินใช้ WMI เข้าช่วย เพื่อให้ง่ายต่อการศึกษา มากกว่าการใช้ API ทั้งหมดครับผม ...

มาดูโค้ดกันเถอะ ... (ส่วนของ Sub Main)
' / -----------------------------------------------------------------------------------------------
' / Developer : Mr.Surapon Yodsanga (Thongkorn Tubtimkrob)
' / eMail : thongkorn@hotmail.com
' / URL: http://www.g2gnet.com (Khon Kaen - Thailand)
' / Facebook: https://www.facebook.com/g2gnet (For Thailand only)
' / Facebook: https://www.facebook.com/commonindy (Worldwide)
' / MORE: http://www.g2gnet.com/webboard
' /
' / Purpose: Get boot disk and read Physical Serial Number.
' / Microsoft Visual Basic 6.0 Service Pack 6
' /
' / This is open source code under @Copyleft by Thongkorn Tubtimkrob.
' / You can modify and/or distribute without to inform the developer.
' / -----------------------------------------------------------------------------------------------

Option Explicit

Sub Main()
    MsgBox "Boot Disk is Serial Number: " & GetBootDiskSerialNumber, , "VB6 Get Boot Hard Disk"
End Sub

Public Function GetBootDiskSerialNumber() As String
On Error Resume Next
    Dim Objs As Object
    Dim Obj As Object
    Dim WMI As Object
    Dim BootDisk As String
    Dim strComputer As String
    Set WMI = GetObject("WinMgmts:")
    For Each Obj In WMI.InstancesOf("Win32_PhysicalMedia")
      If Obj.Tag = "\\.\PHYSICALDRIVE" + CStr(GetBootPhysicalDrive) Then _
            GetBootDiskSerialNumber = Replace(Trim(Obj.SerialNumber), Chr(0), "")
    Next Obj
End Function


มาดูโค้ดในส่วนของโมดูล ... (API - Application Programming Interface)
' / -----------------------------------------------------------------------------------------------
' / Developer : Mr.Surapon Yodsanga (Thongkorn Tubtimkrob)
' / eMail : thongkorn@hotmail.com
' / URL: http://www.g2gnet.com (Khon Kaen - Thailand)
' / Facebook: https://www.facebook.com/g2gnet (For Thailand only)
' / Facebook: https://www.facebook.com/commonindy (Worldwide)
' / MORE: http://www.g2gnet.com/webboard
' /
' / Purpose: Get boot disk and read Physical Serial Number.
' / Microsoft Visual Basic 6.0 Service Pack 6
' /
' / This is open source code under @Copyleft by Thongkorn Tubtimkrob.
' / You can modify and/or distribute without to inform the developer.
' / -----------------------------------------------------------------------------------------------
Option Explicit

Public Const FILE_SHARE_READ = &H1
Public Const FILE_SHARE_WRITE = &H2
Public Const GENERIC_READ = &H80000000
Public Const GENERIC_WRITE = &H40000000
Public Const OPEN_EXISTING = 3

Public Const IOCTL_VOLUME_BASE   As Long = 86 ' Asc("V")
Public Const METHOD_BUFFERED       As Long = 0
Public Const FILE_READ_ACCESS      As Long = 1
Public Const FILE_ANY_ACCESS         As Long = 0

'// DEFINE IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS CTL_CODE(IOCTL_VOLUME_BASE, 0, METHOD_BUFFERED, FILE_ANY_ACCESS)
Public Const IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS = _
    (((IOCTL_VOLUME_BASE) * (2& ^ 16&)) Or _
    ((FILE_ANY_ACCESS) * (2& ^ 14&)) Or _
    ((0&) * (2& ^ 2&)) Or _
    (METHOD_BUFFERED))

Public Type DISK_EXTENT
    DiskNumber      As Long
    StartingOffset      As Currency
    ExtentLength       As Currency
End Type

Public Type VOLUME_DISK_EXTENTS
    NumberOfDiskExtents As Currency
    Extents(1 To 4) As DISK_EXTENT
End Type

Public Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" ( _
    ByVal lpFileName As String, _
    ByVal dwDesiredAccess As Long, _
    ByVal dwShareMode As Long, _
    ByVal lpSecurityAttributes As Long, _
    ByVal dwCreationDisposition As Long, _
    ByVal dwFlagsAndAttributes As Long, _
    ByVal hTemplateFile As Long _
    ) As Long

Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Public Declare Function GetWindowsDirectory Lib "Kernel32.dll" Alias "GetWindowsDirectoryW" ( _
    ByVal lpBuffer As Long, _
    ByVal uSize As Long _
) As Long

Public Declare Function DeviceIoControlNoInput Lib "kernel32" Alias "DeviceIoControl" ( _
    ByVal hDevice As Long, _
    ByVal dwIoControlCode As Long, _
    ByVal lpInBuffer As Long, _
    ByVal nInBufferSize As Long, _
    ByRef lpOutBuffer As Any, _
    ByVal nOutBufferSize As Long, _
    ByRef lpBytesReturned As Long, _
    ByVal lpOverlapped As Long _
    ) As Long

'/ Return the index of the physical drive from which we've booted into Windows.
Public Function GetBootPhysicalDrive() As Long

    Dim sWindowsPath      As String
    Dim nRet                As Long
    Dim sDevicePath         As String
    Dim hLogicalBootDrive   As Long
    Dim sVolumeDevice       As String
    Dim uVolumeDiskExtentsAs VOLUME_DISK_EXTENTS
    Dim nBytesReturned      As Long

    '/ Allocate space and retrieve the windows directory.
    sWindowsPath = Space$(64)
    nRet = GetWindowsDirectory(StrPtr(sWindowsPath), 64)

    '/ This gives us the volume that Windows is on. Open it.
    sVolumeDevice = "\\.\" & Left$(sWindowsPath, 2)
    hLogicalBootDrive = CreateFile(sVolumeDevice, GENERIC_READ + GENERIC_WRITE, FILE_SHARE_READ + FILE_SHARE_WRITE, 0&, OPEN_EXISTING, 0&, 0&)

    '/ Find out information about this volume.
    nRet = DeviceIoControlNoInput(hLogicalBootDrive, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, 0&, 0&, uVolumeDiskExtents, LenB(uVolumeDiskExtents), nBytesReturned, 0&)

    If nRet = 0 Then
      '/ Something went wrong. Return error value.
      GetBootPhysicalDrive = -1
    Else
      '/ This is the physical disk number.
      GetBootPhysicalDrive = uVolumeDiskExtents.Extents(1).DiskNumber
    End If

    '/ Close volume.
    CloseHandle hLogicalBootDrive

End Function



ดาวน์โหลดโค้ดต้นฉบับ VB6 ได้ที่นี่ ...


หน้า: [1]
ดูในรูปแบบกติ: [VB6] อ่านค่า Physical Serial Number ของฮาร์ดดิสต์ที่บู๊ตระบบวินโดวส์ด้วย API