Obtenir le numéro de série de Windows (était: obtenir MachineGuid du registre)

j'essaie de récupérer MachineGuid du Registre, pour créer un certain niveau de liaison avec L'OS pour mon système de licence. De la documentation je peux utiliser

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

pour l'avoir. En outre, les docs me disent que je reçois "default" quand le nom n'est pas trouvé, ou null si la clé n'existe pas. Je devrais avoir une exception de sécurité si je n'y ai pas accès.

le code ci-dessus me donne "default" , ce qui signifie que le nom n'est pas trouvé. Cependant, si je regarde dans le registre avec RegEdit, il est là. Comment puis-je obtenir la valeur MachineGuid d'une application sans privilèges d'administrateur?

Update : lors de l'utilisation de reg.exe Je n'ai aucun problème à obtenir la valeur.

Update : j'ai mis à jour le titre, de sorte que les gens à la recherche d'une façon unique de déterminer L'installation de Windows obtenir ici aussi.

9
demandé sur Bart Friederichs 2013-01-08 14:35:06

3 réponses

comme d'autres personnes l'ont déjà souligné, vous n'êtes pas censé obtenir cette valeur directement à partir du registre (ce qui est probablement la raison pour laquelle il ne fonctionne pas de manière fiable entre les différentes versions de Windows).

une petite recherche m'a mené à la Win32_OperatingSystem classe WMI . En utilisant cette classe, vous pouvez réellement obtenir le numéro de série de Windows. Il m'a fallu un peu de recherche et d'expérimentation pour l'obtenir correctement, mais voici comment l'utiliser in C#.

assurez-vous d'avoir la référence System.Management.dll dans votre projet:

using System.Management;

...

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

avec l'opérateur [] , vous pouvez obtenir n'importe quel bien de la catégorie.

16
répondu Bart Friederichs 2013-01-08 11:30:34

qui est probablement la raison pour laquelle il ne fonctionne pas de manière fiable entre les différentes versions de Windows ""

Non, ce n'est pas la raison. Ce problème est causé par la sélection des cibles de la plate-forme pour votre projet EXE. Projet + Propriétés, onglet créer, une Plate-forme cible zone de liste déroulante. Vous avez mis x86 au lieu de AnyCPU. Sur VS2012, la case à cocher" Prefer 32-bit " est importante. Ce paramètre Force votre programme à fonctionner en mode 32 bits sur une version 64 bits de Windows. Qui a un certain nombre d'effets secondaires, celui qui importe ici est que l'accès aux clés de Registre sont redirigés. Votre programme lit actuellement la valeur de HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\MachineGuid. Qui n'existe pas.

la sélection x86 est la valeur par défaut pour VS2010 et up, auparavant AnyCPU était la valeur par défaut. Microsoft préfère x86, Visual Studio fonctionne mieux avec les processus en mode 32 bits. En particulier lors du débogage, VS est un Le processus 32 bits lui-même nécessite donc le débogueur distant si votre programme exécute en mode 64 bits. Qui a quelques limitations comme le fait de ne pas prendre en charge le débogage en mode mixte. Et la fonctionnalité Edit + Continue ne fonctionne que pour le code 32 bits. Votre programme lui-même fonctionne cependant "mieux" si vous avez le réglage à AnyCPU, y compris ne pas se faire mordre par le système de fichiers et le registre redirection fonctions appcompat intégré dans Windows.

si vous êtes vraiment bloqué avec le mode x86, typiquement parce que vous avez une dépendance sur le code natif 32 bits que vous ne pouvez pas mettre à jour, la solution suivante est d'utiliser le .net 4+ RegistryKey.Méthode OpenBaseKey (). Ce qui vous permet de passer RegistryView.Registry64, s'assurer que vous lirez les clés non-redirigées.

bien sûr, utiliser WMI est une solution. Il suffit de garder à l'esprit que vous êtes et non lisant les mêmes informations lorsque vous utilisez Win32_operatings System.SerialNumber. Dans quelle mesure cette clé est fiable random sur différentes machines n'est pas si clair pour moi, disons juste que cette valeur est une cible assez attrayante pour le genre d'utilisateurs qui ne sont pas très intéressés à payer les frais de licence pour votre produit soit.

enfin et surtout, considérez qu'il est assez facile de générer votre propre id unique qui ne dépend pas du tout de Windows. Avec l'avantage considérable que vous ne serez pas énerver votre client quand il met à jour les fenêtres sur sa machine. Utilisez simplement GUID.NewGuid () une fois et stocke la valeur dans un fichier. Cela sera perdu lorsque le lecteur va mal, mais cela prend généralement votre produit ainsi.

16
répondu Hans Passant 2013-01-08 13:45:36

j'ai mon humble avis, aucune réponse ne répond à la question; est assez simple de demander une façon de lire le MachineGuid à partir du registre... voici donc ma réponse: Vous devez ajouter une référence à "Microsoft.Win32". Ce code a été rédigé à des fins de démonstration et devrait être adapté en conséquence. EDIT: Quelqu'un a déclaré à tort que le code x64 est inutile. Dans l'OS 64 bits qui est où la clé correcte est trouvée. Si cette réponse est la un seul qui répond à la question.

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

J'espère que ça va aider quelqu'un.

6
répondu Darkonekt 2016-09-09 15:16:28