C# 获取唯一的机器 ID
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2004666/
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
get unique machine id
提问by ush
I want to get unique unchangeable Machine id Like Processor serial number of the computer for distribute a software with out copying.
我想获得计算机的唯一不可更改的机器 id 像处理器序列号,以便分发软件而无需复制。
I tried with processor serial number and hard disk serial number that all are changing after formatting and reinstalling the windows.
我尝试使用处理器序列号和硬盘序列号,它们在格式化并重新安装 Windows 后都发生了变化。
Any idea how i can get an unchangeable serial number of a computer?
知道如何获得不可更改的计算机序列号吗?
回答by Blindy
edit: I just saw you meant in c#. Here is a better way with unmanaged code:
编辑:我刚刚看到你在 c# 中的意思。这是使用非托管代码的更好方法:
ManagementClass oMClass = new ManagementClass ("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection colMObj = oMCLass.GetInstances();
foreach(ManagementObject objMO in colMObj)
Console.WriteLine(objMO["MacAddress"].ToString());
回答by Laurent Etiemble
Check out this article. It is very exhaustive and you will find how to extract various hardware information.
看看这篇文章。它非常详尽,您将找到如何提取各种硬件信息。
Quote from the article:
引自文章:
To get hardware information, you need to create an object of ManagementObjectSearcher class.
要获取硬件信息,您需要创建 ManagementObjectSearcher 类的对象。
using System.Management;
ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from " + Key);
foreach (ManagementObject share in searcher.Get()) {
// Some Codes ...
}
The Key on the code above, is a variable that is replaced with appropriate data. For example, to get the information of the CPU, you have to replace the Key with Win32_Processor.
上面代码中的 Key 是一个用适当数据替换的变量。例如,要获取 CPU 的信息,您必须将 Key 替换为 Win32_Processor。
回答by Heinzi
I second Blindy's suggestion to use the MAC address of the (first?) network adapter. Yes, the MAC address can be spoofed, but this has side effects (you don't want two PCs with the same MAC address in the same network), and it's something that "your average pirate" won't do just to be able to use your software. Considering that there's no 100% solution against software piracy, the MAC address is a good compromise, IMO.
我第二个 Blindy 的建议是使用(第一个?)网络适配器的 MAC 地址。是的,MAC 地址可以被欺骗,但这有副作用(您不希望在同一网络中有两台具有相同 MAC 地址的 PC),这是“您的普通盗版者”不会做的事情使用您的软件。考虑到没有 100% 的软件盗版解决方案,MAC 地址是一个很好的折衷方案,IMO。
Note, however, that the address will change when the user adds, replaces or removes a network card (or replaces his old PC altogether), so be prepared to help your customers and give them a new key when they change their hardware configuration.
但是请注意,当用户添加、更换或移除网卡(或完全更换他的旧 PC)时,地址会发生变化,因此请准备好帮助您的客户并在他们更改硬件配置时为他们提供新密钥。
回答by Oliver
If you need a unique ID, you must first decide on your definition of unique. If you want/intend to use it for a copy-protection mechanism, then use something simple. This is because if someone really wants to use your software, (s)he will find a way to break your protection, given enough time and skill. In the case of a unique hardware ID, just think about virtual machines and you'll see that it is possible to spoof anything so someone can tamper with your software.
如果您需要一个唯一 ID,您必须首先确定您对unique的定义。如果您想/打算将其用于复制保护机制,请使用简单的方法。这是因为如果有人真的想使用你的软件,如果有足够的时间和技能,他会找到一种方法来打破你的保护。对于唯一的硬件 ID,只要考虑一下虚拟机,您就会发现可以欺骗任何东西,以便有人可以篡改您的软件。
There is not much you can take from a PC and consider it as uniqueness over its whole lifetime. (Hardware changes will most likely require regenerating the ID at some point.) If you need something like that, you should investigate using an authentication USB Donglewhich you can send to your customers.
您无法从 PC 中获取多少并将其视为其整个生命周期中的唯一性。(硬件更改很可能需要在某个时候重新生成 ID。)如果您需要类似的东西,您应该使用可以发送给客户的身份验证USB 加密狗进行调查。
If you just need some unique identifier that is not as hard to obtain, you could take the MAC address (unreliable), the OS serial number or the domain and user's name, but all of them are susceptible to forgery. However, if your main goal is to lock out unauthorised people, you won't sell anything because no one will want to use your software if it is hard to install, register or to move from one PC to another, although the last consideration is part and parcel of per-machine licensing. (This will likely happen quite often.)
如果您只需要一些不太难获得的唯一标识符,您可以使用 MAC 地址(不可靠)、操作系统序列号或域和用户名,但所有这些都容易被伪造。但是,如果您的主要目标是锁定未经授权的人员,您将不会出售任何东西,因为如果您的软件难以安装、注册或从一台 PC 移动到另一台 PC,那么没有人愿意使用您的软件,尽管最后一个考虑是每台机器许可的一部分。(这可能会经常发生。)
As a first step, make it easy: Use something simple which is not easy to spoof in your target group. (For example, domain and user names can't be easily spoofed by enterprise customers, because their PCs are running in a larger environment implementing policies, etc.) Just forget about the others until you have that.
第一步,让它变得简单:使用简单的东西,不容易在你的目标群体中欺骗。(例如,域和用户名不能轻易被企业客户欺骗,因为他们的 PC 运行在一个更大的环境中,执行策略等。)在你拥有这些之前忘记其他人。
Maybe you can lock them out but that doesn't mean they're going to buy your software; they just won't use it anymore. What you have to consider is how many potential customers won't be or aren't willing to pay because you made it so complicated to use your program.
也许你可以把他们锁在外面,但这并不意味着他们会购买你的软件;他们只是不会再使用它了。您必须考虑的是有多少潜在客户不会或不愿意付款,因为您使使用程序变得如此复杂。
回答by Duncan Bayne
I'd stay well away from using MAC addresses. On some hardware, the MAC address can change when you reboot. We learned quite early during our research not to rely on it.
我会远离使用 MAC 地址。在某些硬件上,重新启动时 MAC 地址可能会更改。我们在研究过程中很早就学会了不要依赖它。
Take a look at the article Developing for Software Protection and Licensingwhich has some pointers on how to design & implement apps to reduce piracy.
看看为软件保护和许可而开发的文章,其中有一些关于如何设计和实施应用程序以减少盗版的指导。
Obligatory disclaimer & plug: the company I co-founded produces the OffByZero Cobalt licensing solution. So it probably won't surprise you to hear that I recommend outsourcing your licensing, & focusing on your core competencies.
强制性免责声明和插件:我共同创立的公司生产OffByZero Cobalt 许可解决方案。因此,听到我建议将您的许可外包并专注于您的核心竞争力,您可能不会感到惊讶。
回答by PRR
You can use WMI Code creator. I guess you can have a combination of "keys" (processorid,mac and software generated key).
您可以使用WMI 代码创建者。我想您可以拥有“密钥”的组合(处理器 ID、mac 和软件生成的密钥)。
using System.Management;
using System.Windows.Forms;
try
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\CIMV2", "SELECT * FROM Win32_Processor");
foreach (ManagementObject queryObj in searcher.Get())
{
Console.WriteLine("-----------------------------------");
Console.WriteLine("Win32_Processor instance");
Console.WriteLine("-----------------------------------");
Console.WriteLine("Architecture: {0}", queryObj["Architecture"]);
Console.WriteLine("Caption: {0}", queryObj["Caption"]);
Console.WriteLine("Family: {0}", queryObj["Family"]);
Console.WriteLine("ProcessorId: {0}", queryObj["ProcessorId"]);
}
}
catch (ManagementException e)
{
MessageBox.Show("An error occurred while querying for WMI data: " + e.Message);
}
Retrieving Hardware Identifiers in C# with WMIby Peter Bromberg
使用 WMI 在 C# 中检索硬件标识符Peter Bromberg
回答by TheGateKeeper
You can try getting some info from the bios. This will still be valid after a format.
您可以尝试从bios中获取一些信息。这在格式化后仍然有效。
回答by Raj kumar
Yes, We could get a code which is combination of Physical Address, Unique Drive ID, Hard Drive ID (Volume Serial), CPU ID and BIOS ID. Example (Full example):
是的,我们可以得到一个代码,它是物理地址、唯一驱动器 ID、硬盘驱动器 ID(卷序列号)、CPU ID 和 BIOS ID 的组合。示例(完整示例):
//Main physical hard drive ID
private static string diskId()
{
return identifier("Win32_DiskDrive", "Model")
+ identifier("Win32_DiskDrive", "Manufacturer")
+ identifier("Win32_DiskDrive", "Signature")
+ identifier("Win32_DiskDrive", "TotalHeads");
}
//Motherboard ID
private static string baseId()
{
return identifier("Win32_BaseBoard", "Model")
+ identifier("Win32_BaseBoard", "Manufacturer")
+ identifier("Win32_BaseBoard", "Name")
+ identifier("Win32_BaseBoard", "SerialNumber");
}
回答by Nik Shev
You should not use MAC, its bad way. Because some OS just changeing it every day. My expirience : Tools.CpuID.ProcessorId() + volumeSerial;
你不应该使用 MAC,这是不好的方式。因为有些操作系统只是每天都在改变它。我的经验:Tools.CpuID.ProcessorId() + volumeSerial;
string volumeSerial = "";
try {
ManagementObject dsk = new ManagementObject(@"win32_logicaldisk.deviceid=""C:""");
dsk.Get();
volumeSerial = dsk["VolumeSerialNumber"].ToString();
} catch {
try {
ManagementObject dsk = new ManagementObject(@"win32_logicaldisk.deviceid=""D:""");
dsk.Get();
volumeSerial = dsk["VolumeSerialNumber"].ToString();
} catch { File.WriteAllText("disk.mising","need C or D"); Environment.Exit(0); }
}
public class CpuID
{
[DllImport("user32", EntryPoint = "CallWindowProcW", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
private static extern IntPtr CallWindowProcW([In] byte[] bytes, IntPtr hWnd, int msg, [In, Out] byte[] wParam, IntPtr lParam);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool VirtualProtect([In] byte[] bytes, IntPtr size, int newProtect, out int oldProtect);
const int PAGE_EXECUTE_READWRITE = 0x40;
public static string ProcessorId()
{
byte[] sn = new byte[8];
if (!ExecuteCode(ref sn))
return "ND";
return string.Format("{0}{1}", BitConverter.ToUInt32(sn, 4).ToString("X8"), BitConverter.ToUInt32(sn, 0).ToString("X8"));
}
private static bool ExecuteCode(ref byte[] result)
{
int num;
/* The opcodes below implement a C function with the signature:
* __stdcall CpuIdWindowProc(hWnd, Msg, wParam, lParam);
* with wParam interpreted as an 8 byte unsigned character buffer.
* */
byte[] code_x86 = new byte[] {
0x55, /* push ebp */
0x89, 0xe5, /* mov ebp, esp */
0x57, /* push edi */
0x8b, 0x7d, 0x10, /* mov edi, [ebp+0x10] */
0x6a, 0x01, /* push 0x1 */
0x58, /* pop eax */
0x53, /* push ebx */
0x0f, 0xa2, /* cpuid */
0x89, 0x07, /* mov [edi], eax */
0x89, 0x57, 0x04, /* mov [edi+0x4], edx */
0x5b, /* pop ebx */
0x5f, /* pop edi */
0x89, 0xec, /* mov esp, ebp */
0x5d, /* pop ebp */
0xc2, 0x10, 0x00, /* ret 0x10 */
};
byte[] code_x64 = new byte[] {
0x53, /* push rbx */
0x48, 0xc7, 0xc0, 0x01, 0x00, 0x00, 0x00, /* mov rax, 0x1 */
0x0f, 0xa2, /* cpuid */
0x41, 0x89, 0x00, /* mov [r8], eax */
0x41, 0x89, 0x50, 0x04, /* mov [r8+0x4], edx */
0x5b, /* pop rbx */
0xc3, /* ret */
};
byte[] code;
if (IsX64Process())
code = code_x64;
else
code = code_x86;
IntPtr ptr = new IntPtr(code.Length);
if (!VirtualProtect(code, ptr, PAGE_EXECUTE_READWRITE, out num))
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
ptr = new IntPtr(result.Length);
try {
return (CallWindowProcW(code, IntPtr.Zero, 0, result, ptr) != IntPtr.Zero);
} catch { System.Windows.Forms.MessageBox.Show("Память повреждена"); return false; }
}
private static bool IsX64Process()
{
return IntPtr.Size == 8;
}
}
回答by Siddhant Jaiswal
There are two ways possible to this that I know:
我知道有两种可能的方法:
Get the Processor id of the system:
public string getCPUId() { string cpuInfo = string.Empty; ManagementClass mc = new ManagementClass("win32_processor"); ManagementObjectCollection moc = mc.GetInstances(); foreach (ManagementObject mo in moc) { if (cpuInfo == "") { //Get only the first CPU's ID cpuInfo = mo.Properties["processorID"].Value.ToString(); break; } } return cpuInfo; }
Get UUID of the system:
public string getUUID() { Process process = new Process(); ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; startInfo.FileName = "CMD.exe"; startInfo.Arguments = "/C wmic csproduct get UUID"; process.StartInfo = startInfo; process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardOutput = true; process.Start(); process.WaitForExit(); string output = process.StandardOutput.ReadToEnd(); return output; }
获取系统的处理器 ID:
public string getCPUId() { string cpuInfo = string.Empty; ManagementClass mc = new ManagementClass("win32_processor"); ManagementObjectCollection moc = mc.GetInstances(); foreach (ManagementObject mo in moc) { if (cpuInfo == "") { //Get only the first CPU's ID cpuInfo = mo.Properties["processorID"].Value.ToString(); break; } } return cpuInfo; }
获取系统的 UUID:
public string getUUID() { Process process = new Process(); ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; startInfo.FileName = "CMD.exe"; startInfo.Arguments = "/C wmic csproduct get UUID"; process.StartInfo = startInfo; process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardOutput = true; process.Start(); process.WaitForExit(); string output = process.StandardOutput.ReadToEnd(); return output; }