2012-06-12 12 views
6

Ho un codice per recuperare un numero di serie del disco rigido dal WMI.Numero di serie HDD WMI trasposto

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

All'inizio ho pensato che funzionasse e ho recuperato il numero di serie corretto. Dopo aver provato ad usarlo con un confronto, ho scoperto il numero che i rapporti WMI non sono esattamente corretti. Il numero di serie WMI è riempito con un sacco di spazi così come i caratteri vengono trasposti.

Il numero di serie dell'unità effettivo stampato sull'adesivo e restituito da alcuni strumenti (probabilmente tramite DeviceIoControl) è "3RH8B1BG", WMI tuttavia restituisce "                                R38H1BGB" .

reale Serial #: 3RH8B1BG
WMI Serial #: R38H1BGB

alcuni strumenti come SiSoftware Sandra, restituire questo numero imbottito e recepito, il numero di serie non è vero però. Il valore WMI è il numero seriale se si traspone ogni altra posizione. È normale? dovrei semplicemente codice per trasporlo al valore corretto?

Cerco di evitare l'utilizzo del WMI ma sembra che qualsiasi ricerca su come eseguire qualcosa sulla rete ora porti indietro gli esempi di WMI.

Il numero di serie del valore WMI per 2 diversi dischi rigidi di diversi produttori sono entrambi trasposti quindi non è un singolo disco.



Aggiornamento: trovato un po 'di codice utilizzando DeviceIoControl

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

Sorprendentemente, DeviceIoControl restituisce un numero di serie recepita pure. Nel codice da CorySmith sopra di esso ha uno SwapChars funzionano

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 

Il codice C menziona ++ ha il flip per:

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

Direi che è standard per DeviceIoControl e WMI, non posso credere qualsiasi degli altri le soluzioni o gli esempi che ho trovato non avevano questo.

+2

Wow, sembra che tu stia correndo su un [PDP-11] (http://en.wikipedia.org/wiki/Endianness#Middle-endian)! – sarnold

+3

In realtà è in esecuzione su un computer con lo stesso byte little-endian che ordina come PDP-11. Lo sono anch'io. E se usi Windows (non Windows CE e non Windows Phone), lo sei anche tu. L'unica soluzione funzionante è chiamare DeviceIoControl e capovolgere i byte personalmente, come trovato nel poster originale. Se chiami WMI, non sai se WMI ha spostato i byte per te o meno. –

risposta

1

Trovato una Soluzione funzionante per decodificare i numeri seriali HD reali. Il seguente link contiene il codice da decodificare anche senza diritti di amministratore: Decoding Source

Ma se si ottengono i numeri di serie dalla classe WMI Win32_PhysicalMedia sopra Vista, potrebbe non funzionare in tutti i casi. Poi devi usare la classe Win32_DiskDrive (secondo questo Link: Jiliang Ge's Answer from Tuesday, October 27, 2009 3:12 AM

Ho aggiunto il codice (in VB, dato che di solito codice in VB.NET). Non volevo rubare il codice di qualcun altro. tante informazioni e ancora alcuni collegamenti al codice originale all'interno del codice. Ora include anche la decodifica dei numeri di serie da unità rimovibili (nella stessa routine).

Spero che aiuti.

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

Pubblicare link non fa bene nessuno. È necessario includere le informazioni pertinenti nella risposta. –

+0

Ci scusiamo per questo. Non volevo rubare il codice da qualcun altro. – dragonfly