且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

WMI的硬盘序列号换位

更新时间:2022-10-25 17:07:03

找到工作解决方案进行解码的真正高清连续剧。下面的链接包含的代码,即使没有管理员权利解码:的解码源



但如果你从上面Vista中的Win32_PhysicalMedia WMI类获得连续出版物可能不会在所有情况下工作。然后,你必须使用Win32_DiskDrive类(根据此链接: 10月27日周二计量戈的回答2009年上午03时12



我添加的代码(在VB,因为我通常是在VB.NET代码)。我不想去偷别人的代码。我包括尽可能多的相关信息,仍然有些链接到在代码中原来的编码器,现在还包括可移动驱动器解码Serialnumbers(在相同的例程)。



希望它帮助。

 '''<总结> 
'''解码Manufacuter磁盘Serialnumbers(也为PNP USB的驱动器)
'''< /总结>
'''< PARAM NAME =InterfaceType> InterfaceType从Win32_DiskDrive WMI级< /参数>
'''< PARAM NAME =PNPDeviceID> PNPDeviceID从Win32_DiskDrive WMI级< /参数>
'''< PARAM NAME =strVolumeSerial>原SERIALNUMBER进行解码和LT; /参数>
'''<返回>解码SERIALNUMBER< /回报>
'''<&言论GT;< /言论>
公共共享功能Decode_HD_Serial(BYVAL InterfaceType作为字符串,
BYVAL PNPDeviceID作为字符串,
BYVAL strVolumeSerial作为字符串)作为字符串

'处理USB PNP设备的不同(可移动USB闪存盘)
'看:http://www.experts-exchange.com/Programming/Languages/.NET/Q_24574066.html

。如果InterfaceType =USB然后
昏暗splitDeviceId作为字符串()= PNPDeviceID.Split(\C)
昏暗arrayLen为整数= splitDeviceId.Length - 1
昏暗的SerialArray作为字符串()= splitDeviceId(arrayLen).Split (&安培;C)
返回的SerialArray(0)
,否则
'链接:HTTPS://social.msdn.microsoft.com/Forums/vstudio/en-US/8523d7b9- 0dc8-4d87-be69-a482aec9ee5e / WMI的win32physicalmedia智能-ID-在Vista中和-7的权限挖掘到[Win32_PhysicalMedia] WMI类?论坛= netfxbcl
'后,我发现,从Vista / Longhorn中的
类已接管了被称为[Win32_DiskDrive另一类。因此,如果所有机器
'在你的环境是Vista和上面使用第二类以其它方式使用第一个。
应用作为管理员或作为非管理员根据我的测试中,当您运行
类提供序列号的独特的形式。
'--- GT&; IF System.Environment.OSVersion.Version.Major> 5那么它的Vista或更高。使用WIN32_DiskDrive

尺寸strVolumeSerialDecoded为String =的String.Empty
'删除所有的空格字符(20)。
'示例:20202020205635424544434553将5635424544434553.
strVolumeSerial.Trim.Replace(20,)
'若用户是Administrator,THE strVolumeSerial字符串已经包含了序列号ASCII和无需转换(?微软的bug),
'但如果strVolumeSerial字符串是一个十六进制字符串,将它转换为ASCII:
如果System.Text.RegularExpressions.Regex.IsMatch(strVolumeSerial, ^ [A-FA-F0-9] + $)然后
'转换为ASCII。例如:5635424544434553将被转换为V5BEDCES。
strVolumeSerial = HexDecode(strVolumeSerial)字符
'交换对。
'实施例:V5BEDCES将被转换为5VEBCDSE。
昏暗serialNumber2作为字符串=
。对于我作为整数= 0〜strVolumeSerial.Length - 1步骤2
strVolumeSerialDecoded&安培; = strVolumeSerial第(i + 1)
strVolumeSerialDecoded&安培; = strVolumeSerial(我)
下一步
'返回SERIALNUMBER为ASCII字符串。
返回strVolumeSerialDecoded.Trim
,否则'如果strVolumeSerial是ASCII,删除空格并返回SERIALNUMBER字符串。
返回strVolumeSerial.Trim
端如果
端如果
端功能

'''<总结>解码十六进制字符串转换为ASCII字符串< /总结>
'''< PARAM NAME =strHEX>在十六进制的字符串解码< /参数>
'''<返回>如果成功,解码后的字符串,空字符串,如果失败< /回报>
私人共享功能HexDecode(BYVAL strHEX作为字符串)作为字符串
尝试
昏暗某人作为StringBuilder的=新的StringBuilder
。对于我作为整数= 0〜strHEX.Length - 1步骤2
sb.Append(Convert.ToChar(Convert.ToUInt32(strHEX.Substring(1,2),16))。的ToString)
下一步
返回sb.ToString
赶上前作为例外
返回,
端尝试
端功能


I have some code to fetch a hard drive serial number from the WMI.

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

At first I thought it was working and retrieved the correct serial number. After trying to use it with a comparison though, I found out the number the WMI reports is not exactly correct. The WMI serial number is padded with a bunch of spaces as well as the characters are transposed.

The actual drive serial number printed on the sticker and returned by some tools (probably using DeviceIoControl) is "3RH8B1BG", WMI however returns "                R38H1BGB".

Real Serial#: 3RH8B1BG
WMI Serial#: R38H1BGB

Some tools like SiSoftware Sandra, return this padded and transposed number, its not actual serial number though. The WMI value is the serial number if you transpose every other position. Is this normal? should I just code to transpose it to the correct value?

I try to avoid using the WMI but it seems any search for how to do something on the net now bring back WMI examples.

The WMI value serial number for 2 different hard drive of different manufactures are both transposed so its not a single disk.



Update: found some code using DeviceIoControl

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

Surprisingly, DeviceIoControl returns a transposed serial number as well. In the code by CorySmith above it has a SwapChars function

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

The c++ code he mentions has the flip to:

    //  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)
{
    ...
}

guess that's standard for DeviceIoControl and WMI, cant believe any of the other solutions or examples i ran across did not have this.

Found a working Solution to decode the real HD-Serials. The following Link contains the code to decode even without admin-rights: Decoding Source

But if you get the Serials from the Win32_PhysicalMedia WMI class above Vista it may not work in all cases. Then you have to use the Win32_DiskDrive class (according to this Link: Jiliang Ge's Answer from Tuesday, October 27, 2009 3:12 AM

I added the code (in VB, since I usually code in VB.NET). I didn't want to steal someone else's Code. I included as much Infos and still some links to the Original Coder within the code. It now also includes decoding Serialnumbers from Removable Drives (in the same routine).

Hope it helps.

   ''' <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