将HDD序列号VB6代码转换为VB.NET代码

5

我有一段很棒的代码,取自一个VC++项目,可以获得硬盘驱动器的完整信息,而不使用WMI(因为WMI有其自身的问题)。

我请求那些熟悉API函数的人尝试将这个VB6代码转换成VB.NET(或C#),并帮助许多非常需要这个实用程序类的人们。

我花了很多时间搜索整个网络,以找到获取HDD实际型号和序列号的方法,最终找到了这个,如果它只是在.NET中...

以下是代码,请原谅其格式问题,只需将其粘贴到VB6 IDE中即可:

Option Explicit

''// Antonio Giuliana, 2001-2003 
''// Costanti per l'individuazione della versione di OS
Private Const VER_PLATFORM_WIN32S = 0
Private Const VER_PLATFORM_WIN32_WINDOWS = 1
Private Const VER_PLATFORM_WIN32_NT = 2

''// Costanti per la comunicazione con il driver IDE
Private Const DFP_RECEIVE_DRIVE_DATA = &H7C088

''// Costanti per la CreateFile
Private Const FILE_SHARE_READ = &H1
Private Const FILE_SHARE_WRITE = &H2
Private Const GENERIC_READ = &H80000000
Private Const GENERIC_WRITE = &H40000000
Private Const OPEN_EXISTING = 3
Private Const CREATE_NEW = 1

''// Enumerazione dei comandi per la CmnGetHDData
Private Enum HDINFO
   HD_MODEL_NUMBER
   HD_SERIAL_NUMBER
   HD_FIRMWARE_REVISION
End Enum

''// Struttura per l'individuazione della versione di OS
Private Type OSVERSIONINFO
   dwOSVersionInfoSize As Long
   dwMajorVersion As Long
   dwMinorVersion As Long
   dwBuildNumber As Long
   dwPlatformId As Long
   szCSDVersion As String * 128
End Type

''// Struttura per il campo irDriveRegs della struttura SENDCMDINPARAMS
Private Type IDEREGS
   bFeaturesReg As Byte
   bSectorCountReg As Byte
   bSectorNumberReg As Byte
   bCylLowReg As Byte
   bCylHighReg As Byte
   bDriveHeadReg As Byte
   bCommandReg As Byte
   bReserved As Byte
End Type

''// Struttura per l'I/O dei comandi al driver IDE
Private Type SENDCMDINPARAMS
    cBufferSize As Long
    irDriveRegs As IDEREGS
    bDriveNumber As Byte
    bReserved(1 To 3) As Byte
    dwReserved(1 To 4) As Long
End Type

''// Struttura per il campo DStatus della struttura SENDCMDOUTPARAMS
Private Type DRIVERSTATUS
    bDriveError As Byte
    bIDEStatus As Byte
    bReserved(1 To 2) As Byte
    dwReserved(1 To 2) As Long
End Type

''// Struttura per l'I/O dei comandi al driver IDE
Private Type SENDCMDOUTPARAMS
    cBufferSize As Long
    DStatus As DRIVERSTATUS     ''// ovvero DriverStatus
    bBuffer(1 To 512) As Byte
End Type

''// Per ottenere la versione del SO
Private Declare Function GetVersionEx _
    Lib "kernel32" Alias "GetVersionExA" _
    (lpVersionInformation As OSVERSIONINFO) As Long

''// Per ottenere un handle al device IDE
Private 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

''// Per chiudere l'handle del device IDE
Private Declare Function CloseHandle _
    Lib "kernel32" _
    (ByVal hObject As Long) As Long

''// Per comunicare con il driver IDE
Private Declare Function DeviceIoControl _
    Lib "kernel32" _
    (ByVal hDevice As Long, _
    ByVal dwIoControlCode As Long, _
    lpInBuffer As Any, _
    ByVal nInBufferSize As Long, _
    lpOutBuffer As Any, _
    ByVal nOutBufferSize As Long, _
    lpBytesReturned As Long, _
    ByVal lpOverlapped As Long) As Long

''// Per azzerare buffer di scambio dati
Private Declare Sub ZeroMemory _
    Lib "kernel32" Alias "RtlZeroMemory" _
    (dest As Any, _
    ByVal numBytes As Long)

''// Per copiare porzioni di memoria
Private Declare Sub CopyMemory _
    Lib "kernel32" Alias "RtlMoveMemory" _
    (Destination As Any, _
    Source As Any, _
    ByVal Length As Long)

Private Declare Function GetLastError _
    Lib "kernel32" () As Long

Private mvarCurrentDrive As Byte    ''// Drive corrente
Private mvarPlatform As String      ''// Piattaforma usata

Public Property Get Copyright() As String
    ''// Copyright
    Copyright = "HDSN Vrs. 1.00, (C) Antonio Giuliana, 2001-2003"
End Property

''// Metodo GetModelNumber
Public Function GetModelNumber() As String
       ''// Ottiene il ModelNumber
    GetModelNumber = CmnGetHDData(HD_MODEL_NUMBER)
End Function

''// Metodo GetSerialNumber
Public Function GetSerialNumber() As String
   ''// Ottiene il SerialNumber
    GetSerialNumber = CmnGetHDData(HD_SERIAL_NUMBER)
End Function

''// Metodo GetFirmwareRevision
Public Function GetFirmwareRevision() As String
   ''// Ottiene la FirmwareRevision
    GetFirmwareRevision = CmnGetHDData(HD_FIRMWARE_REVISION)
End Function

''// Proprieta' CurrentDrive
Public Property Let CurrentDrive(ByVal vData As Byte)
    ''// Controllo numero di drive fisico IDE
    If vData < 0 Or vData > 3 Then
        Err.Raise 10000, , "Illegal drive number"   ''// IDE drive 0..3
    End If

    ''// Nuovo drive da considerare
    mvarCurrentDrive = vData
End Property

''// Proprieta' CurrentDrive
Public Property Get CurrentDrive() As Byte
    ''// Restituisce drive fisico corrente (IDE 0..3)
    CurrentDrive = mvarCurrentDrive
End Property

''// Proprieta' Platform
Public Property Get Platform() As String
    ''// Restituisce tipo OS
    Platform = mvarPlatform
End Property

Private Sub Class_Initialize()
    ''// Individuazione del tipo di OS
    Dim OS As OSVERSIONINFO
   
    OS.dwOSVersionInfoSize = Len(OS)
    Call GetVersionEx(OS)
    mvarPlatform = "Unk"

    Select Case OS.dwPlatformId
        Case Is = VER_PLATFORM_WIN32S
            mvarPlatform = "32S"                ''// Win32S
        Case Is = VER_PLATFORM_WIN32_WINDOWS
            If OS.dwMinorVersion = 0 Then
                mvarPlatform = "W95"            ''// Win 95
            Else
                mvarPlatform = "W98"            ''// Win 98
            End If
        Case Is = VER_PLATFORM_WIN32_NT
            mvarPlatform = "WNT"                ''// Win NT/2000
    End Select
End Sub

Private Function CmnGetHDData(hdi As HDINFO) As String

    ''// Rilevazione proprieta' IDE 
    Dim bin As SENDCMDINPARAMS
    Dim bout As SENDCMDOUTPARAMS
    Dim hdh As Long
    Dim br As Long
    Dim ix As Long
    Dim hddfr As Long
    Dim hddln As Long
    Dim s As String

    Select Case hdi             ''// Selezione tipo caratteristica richiesta
        Case HD_MODEL_NUMBER
            hddfr = 55          ''// Posizione nel buffer del ModelNumber
            hddln = 40          ''// Lunghezza nel buffer del ModelNumber
        Case HD_SERIAL_NUMBER
            hddfr = 21          ''// Posizione nel buffer del SerialNumber
            hddln = 20          ''// Lunghezza nel buffer del SerialNumber
        Case HD_FIRMWARE_REVISION
            hddfr = 47          ''// Posizione nel buffer del FirmwareRevision
            hddln = 8           ''// Lunghezza nel buffer del FirmwareRevision
        Case Else
            Err.Raise 10001, "Illegal HD Data type" 
        End Select

        Select Case mvarPlatform
        Case "WNT"
            ''// Per Win NT/2000 apertura handle al drive fisico
            hdh = CreateFile("\\.\PhysicalDrive" & mvarCurrentDrive, _
                GENERIC_READ + GENERIC_WRITE, FILE_SHARE_READ + FILE_SHARE_WRITE, _
                0, OPEN_EXISTING, 0, 0)
        Case "W95", "W98"
            ''// Per Win 9X apertura handle al driver SMART
            ''// (in \WINDOWS\SYSTEM da spostare in \WINDOWS\SYSTEM\IOSUBSYS)
            ''// che comunica con il driver IDE
            hdh = CreateFile("\\.\Smartvsd", _
                0, 0, 0, CREATE_NEW, 0, 0)
        Case Else
            ''// Piattaforma non supportata (Win32S)
            Err.Raise 10002, , "Illegal platform (only WNT, W98 or W95)"    
    End Select

    ''// Controllo validità handle
    If hdh = 0 Then
        Err.Raise 10003, , "Error on CreateFile"
    End If

    ''// Azzeramento strutture per l'I/O da driver
    ZeroMemory bin, Len(bin)
    ZeroMemory bout, Len(bout)

    ''// Preparazione parametri struttura di richiesta al driver
    With bin
        .bDriveNumber = mvarCurrentDrive
        .cBufferSize = 512
        With .irDriveRegs
            If (mvarCurrentDrive And 1) Then
                .bDriveHeadReg = &HB0
            Else
                .bDriveHeadReg = &HA0
            End If
            .bCommandReg = &HEC
            .bSectorCountReg = 1
            .bSectorNumberReg = 1
        End With
    End With

    ''// Richiesta al driver
    DeviceIoControl hdh, DFP_RECEIVE_DRIVE_DATA, _
                bin, Len(bin), bout, Len(bout), br, 0

    ''// Formazione stringa di risposta
    ''// da buffer di uscita
    ''// L'ordine dei byte e' invertito
    s = ""
    For ix = hddfr To hddfr + hddln - 1 Step 2
        If bout.bBuffer(ix + 1) = 0 Then Exit For
        s = s & Chr(bout.bBuffer(ix + 1))
        If bout.bBuffer(ix) = 0 Then Exit For
        s = s & Chr(bout.bBuffer(ix))
    Next ix

    ''// Chiusura handle
    CloseHandle hdh

    ''// Restituzione informazione richiesta
    CmnGetHDData = Trim(s)

End Function

也许 refactormycode.com 可以更有帮助。 - Tom Ritter
修复了您的代码格式 - 默认格式化无法很好地处理VB。 - Joel Coehoorn
6个回答

5

我找到了!这里是等价的VB.NET代码。它不是VB6代码转换的完全版本,但实现了同样的功能。享受吧!

Public Class HDDInfo
#Region " Declatrations "
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
<System.Runtime.InteropServices.DllImport("kernel32.dll")> _
Private Shared Function CloseHandle(ByVal hObject As Integer) As Integer
End Function
<System.Runtime.InteropServices.DllImport("kernel32.dll")> _
Private Shared Function DeviceIoControl(ByVal hDevice As Integer, ByVal dwIoControlCode As Integer, <[In](), Out()> ByVal lpInBuffer As SENDCMDINPARAMS, ByVal lpInBufferSize As Integer, <[In](), Out()> ByVal lpOutBuffer As SENDCMDOUTPARAMS, ByVal lpOutBufferSize As Integer, _
 ByRef lpBytesReturned As Integer, ByVal lpOverlapped As Integer) As Integer
End Function
Private Const FILE_SHARE_READ As Short = &H1
Private Const FILE_SHARE_WRITE As Short = &H2
Private Const GENERIC_READ As Integer = &H80000000
Private Const GENERIC_WRITE As Integer = &H40000000
Private Const OPEN_EXISTING As Short = 3
Private Const CREATE_NEW As Short = 1
Private Const VER_PLATFORM_WIN32_NT As Integer = 2
Private Const DFP_RECEIVE_DRIVE_DATA As Integer = &H7C088
Private Const INVALID_HANDLE_VALUE As Integer = -1
#End Region
#Region " Classes "
<StructLayout(LayoutKind.Sequential, Size:=8)> _
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
<StructLayout(LayoutKind.Sequential, Size:=32)> _
Private Class SENDCMDINPARAMS
    Public BufferSize As Integer
    Public DriveRegs As IDEREGS
    Public DriveNumber As Byte
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=3)> _
    Public Reserved As Byte()
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=4)> _
    Public Reserved2 As Integer()
    Public Sub New()
        DriveRegs = New IDEREGS()
        Reserved = New Byte(2) {}
        Reserved2 = New Integer(3) {}
    End Sub
End Class
<StructLayout(LayoutKind.Sequential, Size:=12)> _
Private Class DRIVERSTATUS
    Public DriveError As Byte
    Public IDEStatus As Byte
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=2)> _
    Public Reserved As Byte()
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=2)> _
    Public Reserved2 As Integer()
    Public Sub New()
        Reserved = New Byte(1) {}
        Reserved2 = New Integer(1) {}
    End Sub
End Class
<StructLayout(LayoutKind.Sequential)> _
Private Class IDSECTOR
    Public GenConfig As Short
    Public NumberCylinders As Short
    Public Reserved As Short
    Public NumberHeads As Short
    Public BytesPerTrack As Short
    Public BytesPerSector As Short
    Public SectorsPerTrack As Short
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=3)> _
    Public VendorUnique As Short()
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=20)> _
    Public SerialNumber As Char()
    Public BufferClass As Short
    Public BufferSize As Short
    Public ECCSize As Short
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=8)> _
    Public FirmwareRevision As Char()
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=40)> _
    Public ModelNumber As Char()
    Public MoreVendorUnique As Short
    Public DoubleWordIO As Short
    Public Capabilities As Short
    Public Reserved1 As Short
    Public PIOTiming As Short
    Public DMATiming As Short
    Public BS As Short
    Public NumberCurrentCyls As Short
    Public NumberCurrentHeads As Short
    Public NumberCurrentSectorsPerTrack As Short
    Public CurrentSectorCapacity As Integer
    Public MultipleSectorCapacity As Short
    Public MultipleSectorStuff As Short
    Public TotalAddressableSectors As Integer
    Public SingleWordDMA As Short
    Public MultiWordDMA As Short
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=382)> _
    Public Reserved2 As Byte()
End Class
<StructLayout(LayoutKind.Sequential)> _
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
#End Region
#Region " Methods and Functions "
Private Shared Function SwapChars(ByVal chars As Char()) As String
    For i As Integer = 0 To chars.Length - 2 Step 2
        Dim t As Char
        t = chars(i)
        chars(i) = chars(i + 1)
        chars(i + 1) = t
    Next
    Dim s As New String(chars)
    Return s
End Function
Public Shared Function GetHDDInfoString() As String
    Dim serialNumber As String = " ", model As String = " ", firmware As String = " "
    Dim handle As Integer, returnSize As Integer = 0
    Dim driveNumber As Integer = 0
    Dim sci As New SENDCMDINPARAMS()
    Dim sco As New SENDCMDOUTPARAMS()

    If Environment.OSVersion.Platform = PlatformID.Win32NT Then
        handle = CreateFile("\\.\PhysicalDrive" & "0", GENERIC_READ + GENERIC_WRITE, FILE_SHARE_READ + FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0)
    Else
        handle = CreateFile("\\.\Smartvsd", 0, 0, 0, CREATE_NEW, 0, 0)
    End If
    If handle <> INVALID_HANDLE_VALUE Then
        sci.DriveNumber = CByte(driveNumber)
        sci.BufferSize = Marshal.SizeOf(sco)
        sci.DriveRegs.DriveHead = CByte((&HA0 Or driveNumber << 4))
        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)
        End If
        CloseHandle(handle)
    End If
    Return model.Trim & " " & serialNumber.Trim
End Function
#End Region
End Class

1

抱歉,我没有时间为您转换它,但如果没有其他人提供代码,您可以看一下http://www.pinvoke.net。您的VB6代码必须调用Windows API函数来完成工作,而VB.NET代码也必须执行相同的操作。它将调用相同的API函数。

例如,这里是DeviceIoControl页面。

但是,如果您等待足够长的时间,可能会有其他人手头上的代码:-)


1
Try
Dim Searcher_P As New ManagementObjectSearcher("root\CIMV2", "SELECT * FROM Win32_PhysicalMedia")
For Each queryObj As ManagementObject In Searcher_P.Get()
If queryObj("SerialNumber").ToString.Trim = "Y2S0RKFE" Then
Me.Cursor = Cursors.Default
Return True
End If
Next
Catch ex As Exception
MessageBox.Show("An error occurred while querying for WMI data: Win32_PhysicalMedia " & ex.Message)
End Try

Try
Dim Searcher_L As New ManagementObjectSearcher("root\CIMV2", "SELECT * FROM Win32_LogicalDisk WHERE DeviceID = 'C:'")
For Each queryObj As ManagementObject In Searcher_L.Get()
If queryObj("VolumeSerialNumber").ToString.Trim = "226C1A0B" Then
Me.Cursor = Cursors.Default
Return True
End If
Next
Catch ex As Exception
MessageBox.Show("An error occurred while querying for WMI data: VolumeSerialNumber " & ex.Message)
Return False
End Try

你在Web上到处都能看到这种情况。但是在许多情况下它并不起作用,而且会返回Null。我敢打赌,“发生错误时...”的消息会经常出现!这不是我想要的,所以我继续寻找真正能够完成工作的东西。 - Mat

0

对于那些不理解注释中使用的口语的人来说,这是一大堆需要浏览的代码。

我会说这样一句话:在代码中任何你看到 Type 关键字的地方,你可能想要使用 Structure 替代它,.Net 中用于属性的语法略有不同,函数调用需要括号,而 VB.Net 没有“Any”类型(也许可以使用 System.IntPtr 代替?不确定)。

VB.Net 中的大部分语法都是相同的,因此你可能更容易修复我已经提到的问题,然后逐个解决构建出的代码中的每个错误(或错误类型)。


0

是的,我知道VB6,但问题在于API函数声明和传递这些结构(类型)所需的属性。这就是我没有时间去处理的地方! 如果您有自动化的VB6到VB.NET工具和VB6本身,请将代码保存为VB6项目并进行转换。我没有我的VB6。


谁抱怨VB6?从.NET调用外部API基本上是一样的,我已经给出了你需要更新的主要语法差异。做到这一点,然后发布在生成的代码中仍然存在哪些错误。 - Joel Coehoorn
在pInvoke.net中,许多与此代码中定义的类型对应的等效结构不存在。我该在哪里找到它们? - Mat

-1

你可以通过 WMI 获取这些数据。让我给你举个例子。


只是为了澄清一下...根据我的测试,WMI是微软(或其他人)创建的最不可靠的部分。 - newman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接