Получение серийного номера Windows (было: получение MachineGuid из реестра)

Я пытаюсь получить MachineGuid из реестра, чтобы создать некоторый уровень привязки с ОС для моей лицензионной системы. Из документации я могу использовать

string key = "HKEY_LOCAL_MACHINESOFTWAREMicrosoftCryptography";
string r = (string)Registry.GetValue(key, "MachineGuid", (object)"default");

чтобы получить его. Кроме того, врачи говорят мне, что я получаю "default" когда имя не найдено, или null Если ключ не существует. Я должен получить исключение безопасности, если у меня нет доступа.

приведенный выше код дает мне "default", что означает, что имя не найдено. Однако, если я посмотрю в реестре с RegEdit, он там. Как мне получить MachineGuid значение из приложения без прав администратора?

обновление при использовании reg.exe у меня нет проблем с получением значения.

обновление: я обновил название, поэтому люди, которые ищут уникальный способ определения установки Windows, также попадают сюда.

3 ответов


как уже указывали другие люди, Вы не должны получать это значение непосредственно из реестра (вероятно, поэтому он не работает надежно среди разных версий Windows).

небольшой поиск привел меня к Win32_OperatingSystem класс WMI. Используя этот класс, вы можете получить серийный номер Windows. Мне потребовались некоторые поиски и эксперименты, чтобы получить его правильно, но вот как использовать его в C#.

убедитесь, что вы есть System.Management.dll ссылка в вашем проекте:

using System.Management;

...

ManagementObject os = new ManagementObject("Win32_OperatingSystem=@");
string serial = (string)os["SerialNumber"];

С помощью [] оператора, вы можете получить любое свойство в классе.


вероятно, поэтому он не работает надежно среди разных версий Windows

нет, это не причина. Эта проблема вызвана выбором целевой платформы для вашего EXE-проекта. Проект + свойства, вкладка сборки, платформа целевой combobox. У вас установлено значение x86 вместо AnyCPU. На VS2012 имеет значение флажок "предпочесть 32-бит". Этот параметр заставляет программу работать в 32-разрядном режиме на 64-разрядной версии Windows. Который имеет номер из побочных эффектов здесь имеет значение то, что доступ к разделам реестра перенаправляется. Ваша программа фактически считывает значение HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\MachineGuid. Которого не существует.

выбор x86 является значением по умолчанию для VS2010 и выше, ранее AnyCPU был значением по умолчанию. Microsoft предпочитает x86, Visual Studio лучше работает с 32-разрядными режимными процессами. В частности, при отладке VS является 32-разрядным процессом, поэтому требуется удаленный отладчик, если программа выполняется в 64-разрядном режиме. Который имеет несколько ограничений, таких как не поддерживается отладка в смешанном режиме. И функция Edit + Continue работает только для 32-битного кода. Однако ваша программа работает "лучше", если у вас есть настройка в AnyCPU, в том числе не укусить файловую систему и функции перенаправления реестра appcompat, встроенные в Windows.

Если вы действительно застряли в режиме x86, как правило, потому, что у вас есть зависимость от 32-разрядного собственного кода что вы не можете обновить, то следующим обходным путем является использование .NET 4+ RegistryKey.Метод OpenBaseKey (). Что позволяет вам пройти RegistryView.Registry64, гарантируя, что вы будете читать не перенаправленные ключи.

конечно, использование WMI является обходным путем. Просто имейте в виду, что вы не чтение той же информации при использовании Win32_OperatingSystem.Серийный_номер. В какой степени этот ключ надежно случайен на разных машинах, мне не ясно, давайте просто скажем, что это значение является довольно привлекательной целью для пользователей,которые не очень заинтересованы в оплате лицензионного сбора за ваш продукт.

и последнее, но не менее важное: считайте, что довольно легко создать свой собственный уникальный идентификатор, который вообще не зависит от Windows. Со значительным преимуществом, что вы не будете злить своего клиента, когда он обновления Windows на своей машине. Просто используйте Guid.NewGuid () один раз и сохраните значение в файле. Это будет потеряно, когда диск пойдет плохо, но это обычно уничтожает и ваш продукт.


Я мое скромное мнение ни один из ответов не удовлетворяет вопросу; довольно прямолинейно просит способ прочитать MachineGuid из реестра... Итак, вот мой ответ: вам нужно будет добавить ссылку на "Microsoft.Для Win32". Этот код был написан в демонстрационных целях и должен быть соответствующим образом адаптирован. EDIT: кто-то ошибочно заявил, что код x64 бесполезен. В 64-битной ОС, где находится ключ correcty. Таким образом, этот ответ является единственным, который отвечает на вопрос.

private void buttonGetMachineGuid_Click(object sender, RoutedEventArgs e)
{
  try
  {
    string x64Result = string.Empty;
    string x86Result = string.Empty;
    RegistryKey keyBaseX64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
    RegistryKey keyBaseX86 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32);
    RegistryKey keyX64 = keyBaseX64.OpenSubKey(@"SOFTWARE\Microsoft\Cryptography", RegistryKeyPermissionCheck.ReadSubTree);
    RegistryKey keyX86 = keyBaseX86.OpenSubKey(@"SOFTWARE\Microsoft\Cryptography", RegistryKeyPermissionCheck.ReadSubTree);
    object resultObjX64 = keyX64.GetValue("MachineGuid", (object)"default");
    object resultObjX86 = keyX86.GetValue("MachineGuid", (object)"default");
    keyX64.Close();
    keyX86.Close();
    keyBaseX64.Close();
    keyBaseX86.Close();
    keyX64.Dispose();
    keyX86.Dispose();
    keyBaseX64.Dispose();
    keyBaseX86.Dispose();
    keyX64 = null;
    keyX86 = null;
    keyBaseX64 = null;
    keyBaseX86 = null;
    if(resultObjX64 != null && resultObjX64.ToString() != "default")
    {
      MessageBox.Show(resultObjX64.ToString());
    }
    if(resultObjX86 != null && resultObjX86.ToString() != "default")
    {
      MessageBox.Show(resultObjX86.ToString());
    }
  }
  catch(Exception)
  {
  }
}

надеюсь, это кому-то поможет.