2012-06-12 4 views
6

У меня есть код для получения серийного номера жесткого диска из WMI.Серийный номер жесткого диска 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.

Серийный номер значения WMI для 2-х разных жестких дисков разных производителей оба транспонируются таким образом, что не один диск.



Update: найден код с помощью 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, не могу поверить любой другой решения или примеры, с которыми я столкнулся, не имели этого.

+2

Ого, похоже, вы работаете на [PDP-11] (http://en.wikipedia.org/wiki/Endianness#Middle-endian)! – sarnold

+3

На самом деле он работает на компьютере с тем же порядком байтов, что и PDP-11. Я тоже. И если вы используете Windows (а не Windows CE, а не Windows Phone), то и вы. Единственное рабочее решение - вызвать DeviceIoControl и перевернуть байты самостоятельно, как только нашел оригинальный плакат. Если вы вызываете WMI, то вы не знаете, изменил ли WMI байты для вас или нет. –

ответ

1

Нашел рабочее решение для декодирования настоящих HD-серий. Следующая ссылка содержит код для декодирования даже без прав администратора: Decoding Source

Но если вы получите Сериалы из класса WMI Win32_PhysicalMedia выше Vista, это может не работать во всех случаях. Затем вам нужно использовать класс Win32_DiskDrive (в соответствии с этой ссылкой: Jiliang Ge's Answer from Tuesday, October 27, 2009 3:12 AM

Я добавил код (в VB, так как я обычно код на VB.NET). Я не хотел воровать чужой код. а также некоторые ссылки на исходный код в коде. Теперь он также включает в себя декодирование Serialnumbers из Removable Drives (в той же рутине).

Надеюсь, это поможет.

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

Просто публикации ссылок никому не помогают. Вы должны включить соответствующую информацию в свой ответ. –

+0

Извините за это. Я просто не хотел красть код у кого-то другого. – dragonfly

Смежные вопросы