13

我正在尝试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我没有问题获得价值。

更新:我更新了标题,因此寻找确定 Windows 安装的独特方法的人也可以在这里找到。

4

3 回答 3

21

这可能就是为什么它不能在不同版本的 Windows 中可靠工作的原因

不,这不是原因。此问题是由您的 EXE 项目的平台目标选择引起的。项目 + 属性、构建选项卡、平台目标组合框。您将其设置为 x86 而不是 AnyCPU。在 VS2012 上,“首选 32 位”复选框很重要。此设置强制您的程序在 64 位版本的 Windows 上以 32 位模式运行。这有许多副作用,这里重要的是重定向对注册表项的访问。您的程序实际上正在读取 HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\MachineGuid 的值。哪个不存在。

x86 选项是 VS2010 及更高版本的默认选项,之前 AnyCPU 是默认选项。Microsoft 更喜欢 x86,Visual Studio 更适合 32 位模式进程。特别是在调试时,VS 本身是一个 32 位进程,因此如果您的程序在 64 位模式下执行,则需要远程调试器。其中有一些限制,例如不支持混合模式调试。编辑 + 继续功能仅适用于 32 位代码。但是,如果您在 AnyCPU 上进行了设置,您的程序本身会“更好地”运行,包括不会被文件系统和 Windows 内置的注册表重定向 appcompat 功能所困扰。

如果您真的坚持使用 x86 模式,通常是因为您依赖于无法更新的 32 位本机代码,那么下一个解决方法是使用 .NET 4+ RegistryKey.OpenBaseKey() 方法。它允许您通过 RegistryView.Registry64,确保您将读取非重定向键。

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

最后但并非最不重要的一点是,请考虑生成完全不依赖于 Windows 的您自己的唯一 ID 非常容易。具有相当大的优势,即当您的客户在他的机器上更新 Windows 时,您不会惹恼他。只需使用一次 Guid.NewGuid() 并将值存储在文件中。当驱动器出现故障时,这将丢失,但这通常也会导致您的产品失效。

于 2013-01-08T13:45:36.797 回答
20

正如其他人已经指出的那样,您不应该直接从注册表中获取该值(这可能是它在不同版本的 Windows 中无法可靠工作的原因)。

稍微搜索一下,我就找到了WMI 课程。使用这个类,你实际上可以得到 Windows 序列号。我花了一些搜索和试验才能让它正确,但这是在 C# 中使用它的方法。Win32_OperatingSystem

确保您System.Management.dll的项目中有参考:

using System.Management;

...

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

使用[]运算符,您可以获得类中的任何属性。

于 2013-01-08T11:30:34.897 回答
11

我的拙见,没有一个答案能满足这个问题;非常直接地要求一种从注册表中读取 MachineGuid 的方法......所以这是我的答案:您需要添加对“Microsoft.Win32”的引用。此代码是为演示目的而编写的,应进行相应调整。

编辑:有人错误地指出 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)
  {
  }
}

希望这对某人有所帮助。

于 2013-12-01T18:25:37.270 回答