2012-06-12 5 views
6

Tengo un código para obtener un número de serie del disco duro de la WMI.WMI HDD Número de serie transpuesto

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

Al principio pensé que estaba funcionando y recuperé el número de serie correcto. Sin embargo, después de tratar de usarlo con una comparación, descubrí que el número que los informes de WMI no son exactamente correctos. El número de serie de WMI está acolchado con un montón de espacios, así como los caracteres están transpuestos.

El número de serie de unidad real impreso en la etiqueta y devuelto por algunas herramientas (probablemente utilizando DeviceIoControl) es "3RH8B1BG", WMI sin embargo vuelve "                                R38H1BGB" .

real Serial #: 3RH8B1BG
WMI Serial #: R38H1BGB

Algunas herramientas como Clasificador Sandra, devuelva este número acolchado y transpuesta, su número de serie no real sin embargo. El valor de WMI es el número de serie si transpone cualquier otra posición. ¿Esto es normal? ¿Debería codificar para transponerlo al valor correcto?

Intento evitar el uso de WMI pero parece que cualquier búsqueda de cómo hacer algo en la red ahora trae ejemplos de WMI.

El número de serie del valor de WMI para 2 discos duros diferentes de diferentes fabricantes se transpone, por lo que no es un solo disco.



Actualización: encontró un poco de código usando DeviceIoControl

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

Sorprendentemente, DeviceIoControl devuelve un número de serie, así transpuesta. En el código de CorySmith por encima de ella tiene un SwapChars funcionan

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 

El código C++ menciona tiene la cara de:

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

conjetura que es estándar para DeviceIoControl y WMI, no puede creer que cualquiera de los otros soluciones o ejemplos que encontré no tenían esto.

+2

Wow, parece que se está ejecutando en un [PDP-11] (http://en.wikipedia.org/wiki/Endianness#Middle-endian)! – sarnold

+3

Actualmente se está ejecutando en una computadora con el mismo orden de bytes little-endian que el PDP-11. Yo también. Y si está ejecutando Windows (no Windows CE y no Windows Phone), usted también. La única solución que funciona es llamar a DeviceIoControl y voltear los bytes usted mismo, como encontró el póster original. Si llama a WMI, entonces no sabe si WMI volteó los bytes por usted o no. –

Respuesta

1

Encontré una solución que funciona para decodificar los HD-Serials reales. El siguiente enlace contiene el código para decodificar incluso sin derechos de administrador: Decoding Source

Pero si obtiene las publicaciones seriadas de la clase Win32_PhysicalMedia WMI sobre Vista, es posible que no funcione en todos los casos. Luego tiene que usar la clase Win32_DiskDrive (de acuerdo con este enlace: Jiliang Ge's Answer from Tuesday, October 27, 2009 3:12 AM

Agregué el código (en VB, ya que normalmente código en VB.NET). No quería robar el código de otra persona. Incluí tantos Infos y todavía algunos enlaces al codificador original dentro del código. Ahora también incluye la descodificación de números de serie de unidades extraíbles (en la misma rutina).

Espero que ayude.

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

Solo publicar enlaces no le sirve de nada a nadie. Debe incluir la información relevante en su respuesta. –

+0

Perdón por eso. Simplemente no quería robar código de otra persona. – dragonfly

Cuestiones relacionadas