WMI的硬盘序列号换位 [英] WMI HDD Serial Number Transposed

查看:1254
本文介绍了WMI的硬盘序列号换位的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些代码来获取从WMI硬盘驱动器的序列号。



<预类=郎-CS prettyprint-覆盖> SelectQuery selectQuery =新SelectQuery(Win32_PhysicalMedia);
ManagementObjectSearcher搜索=
新ManagementObjectSearcher(selectQuery);
的foreach(的ManagementObject wmi_PM在searcher.Get())
{
字符串str = wmi_PM [的SerialNumber];
}



起初我还以为这是工作和获取正确的序列号。试图虽与比较使用它之后,我发现了WMI报告的数量是不完全正确的。该WMI序列号包着一堆以及字符被调换的空间。



印刷在贴纸并返回由一些工具(可能是实际的驱动器序列号使用的DeviceIoControl)为3RH8B1BG,WMI却返回&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP; R38H1BGB。



真正的连环#:3RH8B1BG

WMI序列号:R38H1BGB



一些工具,如SiSoftware Sandra里虽然返回此衬垫和转数,它不是实际的序列号。该WMI值是序列号,如果你每转其他职务。这正常吗?我只是代码将其移至正确的价值?



我会尽量避免使用WMI,但它似乎怎么办在网上的东西,现在带回WMI例子任何搜索。



生产用于不同的2种不同的硬盘驱动器的WMI值的序列号都被调换所以它不是一个单一的磁盘。







更新:发现使用的DeviceIoControl


&NBSP一些代码; NBSP&; NBSP&; NBSP&; NBSP&;的 http://addressof.com/blog/archive/2004/02/14/392.aspx


令人惊讶地,DeviceIoControl的返回一个转置的序列号为好。
在由CorySmith上面的代码它有一个SwapChars功能



 专用共享功能SwapChars(BYVAL字符()为CHAR )作为字符串
。对于我作为整数= 0〜chars.Length - 2步骤2
chars.Reverse(字符,1,2)
下一步
返回新建字符串(字符) .Trim
端功能

C ++的,他提到代码具有翻转为:



<预类=郎-C prettyprint-覆盖> //功能IDE硬盘
的序列号//使用IOCTL_STORAGE_QUERY_PROPERTY命令解码
的char * flipAndCodeBytes(为const char * str中,
INT POS,
INT翻转,
的char * BUF)
{
...
}

想这是对的DeviceIoControl和WMI,斜面标准相信任何其他的解决方案或例子我跑的横跨没有这个。


解决方案

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



但如果你从上面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

这篇关于WMI的硬盘序列号换位的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆