如何在 C# 中获取 Windows 产品密钥?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10926634/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I get windows product key in C#?
提问by lovin
How can I get windows product key in C# ?
如何在 C# 中获取 Windows 产品密钥?
I want to get some key like windows key from client side.
我想从客户端获取一些像 Windows 键这样的键。
回答by Eric J.
Check out Windows Product Key Finder.
查看 Windows 产品密钥查找器。
Source is available.
来源可用。
The key is stored in the registry and needs to be decoded using an algorithm available in the source.
密钥存储在注册表中,需要使用源中可用的算法进行解码。
回答by Gaurav Agrawal
Using this code, you can find the product key of your Microsoft products.
使用此代码,您可以找到 Microsoft 产品的产品密钥。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32;
namespace MSKeyFinder
{
public class KeyDecoder
{
public enum Key { XP, Office10, Office11 };
public static byte[] GetRegistryDigitalProductId(Key key)
{
byte[] digitalProductId = null;
RegistryKey registry = null;
switch (key)
{
// Open the XP subkey readonly.
case Key.XP:
registry =
Registry.LocalMachine.
OpenSubKey(
@"SOFTWARE\Microsoft\Windows NT\CurrentVersion",
false);
break;
// Open the Office 10 subkey readonly.
case Key.Office10:
registry =
Registry.LocalMachine.
OpenSubKey(
@"SOFTWARE\Microsoft\Office.0\Registration\" +
@"{90280409-6000-11D3-8CFE-0050048383C9}",
false);
// TODO: Open the registry key.
break;
// Open the Office 11 subkey readonly.
case Key.Office11:
// TODO: Open the registry key.
break;
}
if (registry != null)
{
// TODO: For other products, key name maybe different.
digitalProductId = registry.GetValue("DigitalProductId")
as byte[];
registry.Close();
}
return digitalProductId;
}
public static string DecodeProductKey(byte[] digitalProductId)
{
// Offset of first byte of encoded product key in
// 'DigitalProductIdxxx" REG_BINARY value. Offset = 34H.
const int keyStartIndex = 52;
// Offset of last byte of encoded product key in
// 'DigitalProductIdxxx" REG_BINARY value. Offset = 43H.
const int keyEndIndex = keyStartIndex + 15;
// Possible alpha-numeric characters in product key.
char[] digits = new char[]
{
'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'M', 'P', 'Q', 'R',
'T', 'V', 'W', 'X', 'Y', '2', '3', '4', '6', '7', '8', '9',
};
// Length of decoded product key
const int decodeLength = 29;
// Length of decoded product key in byte-form.
// Each byte represents 2 chars.
const int decodeStringLength = 15;
// Array of containing the decoded product key.
char[] decodedChars = new char[decodeLength];
// Extract byte 52 to 67 inclusive.
ArrayList hexPid = new ArrayList();
for (int i = keyStartIndex; i <= keyEndIndex; i++)
{
hexPid.Add(digitalProductId[i]);
}
for (int i = decodeLength - 1; i >= 0; i--)
{
// Every sixth char is a separator.
if ((i + 1) % 6 == 0)
{
decodedChars[i] = '-';
}
else
{
// Do the actual decoding.
int digitMapIndex = 0;
for (int j = decodeStringLength - 1; j >= 0; j--)
{
int byteValue = (digitMapIndex << 8) | (byte)hexPid[j];
hexPid[j] = (byte)(byteValue / 24);
digitMapIndex = byteValue % 24;
decodedChars[i] = digits[digitMapIndex];
}
}
}
return new string(decodedChars);
}
}
}
Referenced by : http://www.codeproject.com/Articles/23334/Microsoft-Product-Key-Finder
参考:http: //www.codeproject.com/Articles/23334/Microsoft-Product-Key-Finder
回答by Roman Sokk
回答by Damien_The_Unbeliever
WMI has a class, called Win32_OperatingSystemthat contains a property called SerialNumber:
WMI 有一个名为的类,Win32_OperatingSystem其中包含一个名为SerialNumber的属性:
Operating system product serial identification number.
Example: "10497-OEM-0031416-71674"
操作系统产品序列号。
示例:“10497-OEM-0031416-71674”
The System.Managementnamespace contains classes that allow .NET code to interact with WMI.
该System.Management命名空间包含的类允许.NET代码与WMI交互。
回答by mrpeardotnet
Windows Product Key Finder and other solutions mentioned here by Erij J. and others are working for Windows XP and Windows 7 only. Microsoft has changed key encryption algorithm since Windows 8.
Windows Product Key Finder 和 Erij J. 和其他人在此提到的其他解决方案仅适用于 Windows XP 和 Windows 7。自 Windows 8 起,Microsoft 更改了密钥加密算法。
I've found a solution for Windows 8 and up on blogpost here: http://winaero.com/blog/how-to-view-your-product-key-in-windows-10-windows-8-and-windows-7/
我在这里的博客文章中找到了适用于 Windows 8 及更高版本的解决方案:http://winaero.com/blog/how-to-view-your-product-key-in-windows-10-windows-8-and-windows -7/
However it is written in VBS, so I've rewritten it to C#.
但是它是用 VBS 编写的,所以我将它重写为 C#。
You can check full project on GitHub: https://github.com/mrpeardotnet/WinProdKeyFinder
你可以在 GitHub 上查看完整的项目:https: //github.com/mrpeardotnet/WinProdKeyFinder
Here is the code how to decode product key in Windows 8 and up:
以下是如何在 Windows 8 及更高版本中解码产品密钥的代码:
public static string DecodeProductKeyWin8AndUp(byte[] digitalProductId)
{
var key = String.Empty;
const int keyOffset = 52;
var isWin8 = (byte)((digitalProductId[66] / 6) & 1);
digitalProductId[66] = (byte)((digitalProductId[66] & 0xf7) | (isWin8 & 2) * 4);
// Possible alpha-numeric characters in product key.
const string digits = "BCDFGHJKMPQRTVWXY2346789";
int last = 0;
for (var i = 24; i >= 0; i--)
{
var current = 0;
for (var j = 14; j >= 0; j--)
{
current = current*256;
current = digitalProductId[j + keyOffset] + current;
digitalProductId[j + keyOffset] = (byte)(current/24);
current = current%24;
last = current;
}
key = digits[current] + key;
}
var keypart1 = key.Substring(1, last);
const string insert = "N";
key = key.Substring(1).Replace(keypart1, keypart1 + insert);
if (last == 0)
key = insert + key;
for (var i = 5; i < key.Length; i += 6)
{
key = key.Insert(i, "-");
}
return key;
}
To check Windows version and get digitalProductId use wrapper method like this:
要检查 Windows 版本并获取 digitalProductId 使用如下包装方法:
public static string GetWindowsProductKey()
{
var key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
RegistryView.Default);
const string keyPath = @"Software\Microsoft\Windows NT\CurrentVersion";
var digitalProductId = (byte[])key.OpenSubKey(keyPath).GetValue("DigitalProductId");
var isWin8OrUp =
(Environment.OSVersion.Version.Major == 6 && System.Environment.OSVersion.Version.Minor >= 2)
||
(Environment.OSVersion.Version.Major > 6);
var productKey = isWin8OrUp ? DecodeProductKeyWin8AndUp(digitalProductId) : DecodeProductKey(digitalProductId);
return productKey;
}
I've tested it on several machines and it was giving me correct results. Even on Windows 10 I was able to get generic Windows 10 code (on upgraded system).
我已经在几台机器上测试过它,它给了我正确的结果。即使在 Windows 10 上,我也能够获得通用的 Windows 10 代码(在升级的系统上)。
Note: For me the original vbs script was returning wrong Win7 keys despite the fact that original blogpost states the code works for Win7 and up. So I always fallback to the well known old method for Win7 and lower.
注意:对我来说,尽管原始博客文章指出代码适用于 Win7 及更高版本,但原始 vbs 脚本返回了错误的 Win7 键。所以我总是回退到 Win7 及更低版本的众所周知的旧方法。
Hope it helps.
希望能帮助到你。
回答by Diablo 3
Going with mrpeardotnet'sanswer...
使用mrpeardotnet的答案......
I was getting errors where RegistryView.Defaultwould not convert to string.
I changed this:
我在RegistryView.Default无法转换为字符串的地方遇到错误。我改变了这个:
var key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default);
to this:
对此:
var key = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, Environment.MachineName);
and it seems to work.
它似乎有效。

