获取Windows序列号(原来是:从注册表中获取MachineGuid)

本文关键字:获取 注册表 MachineGuid Windows 序列号 原来 | 更新日期: 2023-09-27 17:51:02

我正试图从注册表中获取MachineGuid,以便为我的许可证系统创建与操作系统的某种程度的绑定。从文档中我可以使用

string key = "HKEY_LOCAL_MACHINE''SOFTWARE''Microsoft''Cryptography";
string r = (string)Registry.GetValue(key, "MachineGuid", (object)"default");

得到它。此外,文档告诉我,当没有找到名称时,我得到"default",或者如果密钥不存在,我得到null。如果我没有访问权限,我应该得到一个安全异常。

上面的代码给出了"default",这意味着没有找到名称。但是,如果我用RegEdit查看注册表,它就在那里。如何从没有管理员权限的应用程序中获取MachineGuid值?

更新:当使用reg.exe时,我没有问题获得值。

Update:我更新了标题,所以人们寻找一种独特的方式来确定Windows安装也到这里。

获取Windows序列号(原来是:从注册表中获取MachineGuid)

正如其他人已经指出的那样,您不应该直接从注册表中获得该值(这可能就是为什么它在不同版本的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项目的平台目标选择引起的。项目+属性,构建选项卡,平台目标组合框。您将其设置为x86而不是AnyCPU。在VS2012上,"Prefer 32-bit"复选框很重要。此设置强制您的程序在64位版本的Windows上以32位模式运行。这有许多副作用,这里重要的是对注册表项的访问被重定向。你的程序实际上正在读取HKEY_LOCAL_MACHINE'SOFTWARE'Wow6432Node'Microsoft'Cryptography'MachineGuid的值。这是不存在的

x86选项是VS2010及更高版本的默认选项,之前AnyCPU是默认选项。微软更喜欢x86, Visual Studio更适合32位模式进程。特别是在调试时,VS本身是一个32位进程,因此如果您的程序以64位模式执行,则需要远程调试器。它有一些限制,比如不支持混合模式调试。编辑+继续功能只适用于32位代码。然而,如果你在AnyCPU上设置,你的程序本身就会"更好"地工作,包括不被Windows内置的文件系统和注册表重定向appcompat功能咬伤。

如果你真的被x86模式困住了,通常是因为你对32位本地代码有依赖而无法更新,那么下一个解决方法是使用。net 4+ RegistryKey.OpenBaseKey()方法。它允许你传递RegistryView。Registry64,确保您将读取非重定向键。

当然,使用WMI是一种变通方法。请记住,当您使用Win32_OperatingSystem.SerialNumber时,您是而不是读取相同的信息。我不太清楚这个密钥在不同机器上的可靠随机程度,我们只能说,对于那些对支付产品许可费也不太感兴趣的用户来说,这个值是一个非常有吸引力的目标。

最后但并非最不重要的是,一定要考虑到生成自己的唯一id非常容易,完全不依赖于Windows。有相当大的优势,你不会惹恼你的客户,当他在他的机器上更新Windows。只需使用一次Guid.NewGuid()并将值存储在文件中。当驱动器坏掉时,它会丢失,但这通常也会带走你的产品。

依我之见,没有一个答案能满足这个问题;非常直接地要求从注册表中读取MachineGuid的方法……所以我的回答是:你需要添加一个"microsoft . win32"的引用。这段代码是为了演示而编写的,应该相应地进行修改。

EDIT:有人错误地说x64代码是无用的。
在64位操作系统中,这是找到正确密钥的地方。

所以这个答案是唯一满足这个问题的答案。

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