Jumat, 14 Agustus 2020

Vb.Net: Serial Number Hard Disk Dari Manufacture/ Factory (Pabrikan)


Banyak pertanyaan di lembaga-lembaga programming tentang bagaimana mendapatkan serial number hardisk yang bawaan dari pabriknya. Tapi bukan yang serial number volume yah, sebab serial volume akan berubah2 ketika proses format. Kebanyakan code yang Rani temukan memakai WMI, namun serial number yang dihasilkan tak sesuai keinginan.

Rani pengennya serial number yang sama yang umumnya dihasilkan oleh code HDSN mirip yang di link Planet Source Code, dan code ini sebelumnya Rani pakai di aplikasi-aplikasi yang memakai Visual Basic 6 (VB6). Dan sekarang saat migrasi aplikasi ke VB.NET Rani butuh code yang sama, sayangnya klo memakai WMI jadinya ga sama. Berarti harus cari cara selain memakai WMI, ada ga ya?

Akhirnya dapet solusi terbaik dengan menggunakan DeviceIOControl yang diperoleh dari blog jo0ls' .Net stuff. Kemudian Rani penyesuaian sesuai kebutuhan.

Caranya sehabis membuat project/solution windows form bernama HDDSerial Number, tambahkan sebuah module berjulukan SerialNumber.vb
Kemudian tambahkan code selaku berikut:
Imports System.Runtime.InteropServicesImports Microsoft.Win32.SafeHandlesImports System.SecurityImports System.ComponentModelImports System.Text

Module SerialNumber

  _
  Private Class NativeMethods
      "kernel32"
, SetLastError:=True)> _
      Public Shared Function CreateFile( _
       ByVal FileName As String, _
       ByVal DesiredAccess As Integer, _
      
ByVal ShareMode As Integer, _
      
ByVal SecurityAttributes As IntPtr, _
      
ByVal CreationDisposition As Integer, _
      
ByVal FlagsAndAttributes As Integer, _
      
ByVal hTemplateFile As IntPtr) As SafeFileHandle
      End Function

      "kernel32.dll"
, SetLastError:=True)> _
      Friend Shared Function DeviceIoControl( _
          ByVal deviceHandle As SafeFileHandle, _
          ByVal controlCode As Integer, _
          ByRef inBuffer As ATA_PASS_THROUGH_EX_WITH_BUFFERS, _
          ByVal inBufferSize As Integer, _
          ByRef outBuffer As ATA_PASS_THROUGH_EX_WITH_BUFFERS, _
          ByVal outBufferSize As Integer, _
          ByRef bytesReturned As Integer, _
          ByVal overlapped1 As IntPtr) As Boolean
      End Function

  End Class


  _
  Private Structure ATA_PASS_THROUGH_EX
      Public Length As Short
     
Public AtaFlags As Short
     
Public PathId As Byte
     
Public TargetId As Byte
     
Public Lun As Byte
     
Public ReservedAsUchar As Byte
     
Public DataTransferLength As Integer
     
Public TimeOutValue As Integer
     
Public ReservedAsUlong As Integer
     
Public DataBufferOffset As IntPtr
      _
     
Public PreviousTaskFile() As Byte
      _
     
Public CurrentTaskFile() As Byte
  End Structure

  _
  Private Structure ATA_PASS_THROUGH_EX_WITH_BUFFERS
      Public Apt As ATA_PASS_THROUGH_EX
      _
      Public Data() As Byte
  End Structure

  Public Enum HDINFO
      HD_MODEL_NUMBER = 0
      HD_SERIAL_NUMBER = 1
      HD_FIRMWARE_REVISION = 2
  End Enum

  Public Function HDDInfo(ByVal InfoType As HDINFO) As String
      Dim letter As Char = "c"
      Const GenericRead As Integer = &H80000000
     
Const GenericWrite As Integer = &H40000000
     
Const FileShareRead As Integer = 1
     
Const FileShareWrite As Integer = 2
     
Const OpenExisting As Integer = 3
      Dim drivePath As String = String.Concat("\\.\" & letter & ":")
      Using driveHandle As SafeFileHandle = NativeMethods.CreateFile( _
       drivePath, _
       GenericRead Or GenericWrite, _
       FileShareRead Or FileShareWrite, _
       IntPtr.Zero, _
       OpenExisting, _
       0, _
       IntPtr.Zero)
          If driveHandle.IsInvalid Then
             Return "CreateFile ERROR: " & (New Win32Exception).Message
          End If
          Dim apex As New ATA_PASS_THROUGH_EX
          apex.Length = Marshal.SizeOf(apex)

          ' ATA_FLAGS_DATA_IN
          apex.AtaFlags = 2

          ' The command returns a 512 byte package of informasi.
          apex.DataTransferLength = 512

          apex.TimeOutValue = 10 ' 10 second timeout.
          apex.DataBufferOffset = Marshal.OffsetOf( _
                    GetType(ATA_PASS_THROUGH_EX_WITH_BUFFERS), "Data")
          ' This contains the command we are requesting.
          apex.CurrentTaskFile = New Byte(7)
          'the command "IDENTIFY DEVICE"
          apex.CurrentTaskFile(6) = &HEC
          Dim apexb As New ATA_PASS_THROUGH_EX_WITH_BUFFERS
          apexb.Apt = apex
          Dim inBufferSize As Integer = Marshal.SizeOf( _
                   GetType(ATA_PASS_THROUGH_EX_WITH_BUFFERS))
          Dim bytesReturned As Integer
          Const IOCTL_ATA_PASS_THROUGH As Integer = &H4D02C
          Dim result As Boolean = NativeMethods.DeviceIoControl( _
                                  driveHandle, IOCTL_ATA_PASS_THROUGH, _
                                  apexb, inBufferSize, apexb, inBufferSize, _
                                  bytesReturned, IntPtr.Zero)
          If result = False Then
              Return "DeviceIOControl ERROR: " & (New Win32Exception).Message
          End If

          Select
Case InfoType
             
Case HDINFO.HD_SERIAL_NUMBER
                 
Return GetString(apexb.Data, 20, 20)
             
Case HDINFO.HD_FIRMWARE_REVISION
                 
Return GetString(apexb.Data, 46, 8)
             
Case HDINFO.HD_MODEL_NUMBER
                  Return GetString(apexb.Data, 54, 40)
              Case Else
                  Return Nothing

          End Select
      End Using
  End Function


  Private Function GetString(ByVal bytes() As Byte, _
                            
ByVal offset As Integer, _
                            
ByVal length As Integer) As String
      ' The strings are slightly weird - endianness?
      ' If you use ASCII.GetBytes Then Each character
      ' pair is reversed.

      Dim sb As New StringBuilder()
      For i As Integer = offset To offset + length - 1 Step 2
          sb.Append(Chr(bytes(i + 1)))
          sb.Append(Chr(bytes(i)))
      Next
      Return
RTrim(LTrim(sb.ToString))
  End Function

End Module


Atur UI pada Form1 biar property text menjadi "Hardisk Serial Number", tambahkan 3 label dan 3 TextBox. Berinama textbox-textbox tersebut dengan txtSerialNumber, txtModel, dan txtFirmware.
Kemudian ketikan arahan berikut:
Imports System.Management

Public Class Form1
    Private Sub Form1_Load(ByVal sender As Object, _

          ByVal e As EventArgs) Handles MyBase.Load

        Try

            txtSerialNumber.Text = HDDInfo(HDINFO.HD_SERIAL_NUMBER)
            txtModel.Text = HDDInfo(HDINFO.HD_MODEL_NUMBER)
            txtFirmware.Text = HDDInfo(HDINFO.HD_FIRMWARE_REVISION)

        Catch ex As Exception
            MsgBox(ex.Message)
        End Try

    End Sub
End Class

Jalankan, dan ini penampakan hasil di PC Rani:

Catatan: Jangan lupa untuk Run as Administrator agar aplikasi mampu berjalan baik pada Vista, Windows 7, dan Windows 8.

Referensi:
http://stackoverflow.com/questions/782053/get-hdd-and-not-volume-serial-number-on-vista-ultimate-64-bit
we.com/search?q=getting-hard-disk-drive-info-with

Click here if you like this article.



Sumber http://rani-irsan.blogspot.com


EmoticonEmoticon