簡體   English   中英

轉換WMI HDD序列號

[英]WMI HDD Serial Number Transposed

我有一些代碼從WMI獲取硬盤序列號。

SelectQuery selectQuery = new SelectQuery("Win32_PhysicalMedia");
ManagementObjectSearcher searcher =
             new ManagementObjectSearcher(selectQuery);
foreach (ManagementObject wmi_PM in searcher.Get())
{
      string str = wmi_PM["SerialNumber"];
}

起初我認為它正在工作並檢索到正確的序列號。 在嘗試使用它進行比較之后,我發現WMI報告的數字並不完全正確。 WMI序列號用一堆空格填充,並且字符被轉置。

打印在貼紙上並由某些工具(可能使用DeviceIoControl)返回的實際驅動器序列號為“3RH8B1BG”,但WMI返回“R38H1BGB”。

Real Serial#:3RH8B1BG
WMI Serial#:R38H1BGB

一些工具,如SiSoftware Sandra,返回這個填充和轉置的數字,但它不是實際的序列號。 如果您轉換每個其他位置,WMI值是序列號。 這是正常的嗎? 我應該只是編碼將其轉換為正確的值嗎?

我試圖避免使用WMI,但似乎任何搜索如何在網上做某事現在帶回WMI的例子。

不同制造商的2個不同硬盤的WMI值序列號都被轉置,因此它不是單個磁盤。



更新:使用DeviceIoControl找到一些代碼

http://addressof.com/blog/archive/2004/02/14/392.aspx

令人驚訝的是,DeviceIoControl也返回轉置的序列號。 在上面的CorySmith代碼中,它有一個SwapChars函數

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

他提到的c ++代碼有以下幾點:

    //  function to decode the serial numbers of IDE hard drives
    //  using the IOCTL_STORAGE_QUERY_PROPERTY command 
char * flipAndCodeBytes (const char * str,
             int pos,
             int flip,
             char * buf)
{
    ...
}

猜測這是DeviceIoControl和WMI的標准,不能相信我遇到的任何其他解決方案或示例都沒有這個。

找到了解決真正的HD-Serials的工作解決方案。 以下鏈接包含即使沒有管理員權限也要解碼的代碼: 解碼源

但是如果你從Vista上面的Win32_PhysicalMedia WMI類獲得Serials,它可能無法在所有情況下使用。 然后你必須使用Win32_DiskDrive類(根據這個鏈接: Jiliang Ge的答案,從2009年10月27日星期二上午3:12

我添加了代碼(在VB中,因為我通常在VB.NET中編寫代碼)。 我不想偷別人的代碼。 我在代碼中包含了盡可能多的信息和一些原始編碼器的鏈接。 它現在還包括解碼可移動驅動器中的Serialnumbers(在同一例程中)。

希望能幫助到你。

   ''' <summary>
''' Decode Manufacuter Disk Serialnumbers (also for PNP USB-Drives)
''' </summary>
''' <param name="InterfaceType">InterfaceType from Win32_DiskDrive WMI-Class</param>
''' <param name="PNPDeviceID">PNPDeviceID from Win32_DiskDrive WMI-Class</param>
''' <param name="strVolumeSerial">Raw Serialnumber to be decoded</param>
''' <returns>Decoded Serialnumber</returns>
''' <remarks></remarks>
Public Shared Function Decode_HD_Serial(ByVal InterfaceType As String,
                          ByVal PNPDeviceID As String,
                          ByVal strVolumeSerial As String) As String

    'HANDLE USB PNP Devices differently (Removable USB-Sticks)
    'see: http://www.experts-exchange.com/Programming/Languages/.NET/Q_24574066.html

    If InterfaceType = "USB" Then
        Dim splitDeviceId As String() = PNPDeviceID.Split("\"c)
        Dim arrayLen As Integer = splitDeviceId.Length - 1
        Dim serialArray As String() = splitDeviceId(arrayLen).Split("&"c)
        Return serialArray(0)
    Else
        'Link:https://social.msdn.microsoft.com/Forums/vstudio/en-US/8523d7b9-0dc8-4d87-be69-a482aec9ee5e/wmi-win32physicalmedia-smart-id-in-vista-and-7-permissions?forum=netfxbcl
        'After digging into the [Win32_PhysicalMedia] WMI class, I find that from Vista/Longhorn the 
        'class has been taken over by another class called [Win32_DiskDrive]. Thus, if all machines 
        'in your environment are Vista and above use the second class otherwise use the first one. 
        'Based on my tests, the class gives the unique form of serial number when you run the 
        'app as an admin or as a non-admin. 
        ' ---> IF System.Environment.OSVersion.Version.Major > 5 then its Vista or higher. USE WIN32_DiskDrive

        Dim strVolumeSerialDecoded As String = String.Empty
        'Remove all space characters ("20").
        'Example : 20202020205635424544434553 will be 5635424544434553.
        strVolumeSerial.Trim.Replace("20", "")
        'IF THE USER IS ADMINISTRATOR, THE strVolumeSerial STRING WILL ALREADY CONTAIN THE SERIAL NUMBER IN ASCII, AND NO CONVERSION IS REQUIRED (Microsoft bug ?),
        'BUT IF THE strVolumeSerial STRING IS A HEX STRING, CONVERT IT TO ASCII :
        If System.Text.RegularExpressions.Regex.IsMatch(strVolumeSerial, "^[a-fA-F0-9]+$") Then
            'Convert to ASCII. Example : 5635424544434553 will be converted to V5BEDCES.
            strVolumeSerial = HexDecode(strVolumeSerial)
            'Swap pairs of characters.
            'Example : V5BEDCES will be converted to 5VEBCDSE.
            Dim serialNumber2 As String = ""
            For i As Integer = 0 To strVolumeSerial.Length - 1 Step 2
                strVolumeSerialDecoded &= strVolumeSerial(i + 1)
                strVolumeSerialDecoded &= strVolumeSerial(i)
            Next
            'Return the serialnumber as ASCII string.
            Return strVolumeSerialDecoded.Trim
        Else 'If strVolumeSerial is ASCII, remove spaces and return the serialnumber string.
            Return strVolumeSerial.Trim
        End If
    End If
End Function

''' <summary>Decodes a HEX-string to an ASCII string.</summary>
''' <param name="strHEX">The HEX-string to decode.</param>
''' <returns>If succeeded, the decoded String, an empty String if failed.</returns>
Private Shared Function HexDecode(ByVal strHEX As String) As String
    Try
        Dim sb As StringBuilder = New StringBuilder
        For i As Integer = 0 To strHEX.Length - 1 Step 2
            sb.Append(Convert.ToChar(Convert.ToUInt32(strHEX.Substring(i, 2), 16)).ToString)
        Next
        Return sb.ToString
    Catch ex As Exception
        Return ""
    End Try
End Function

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM