获得唯一的机器ID

我想得到唯一不变的机器ID像计算机的处理器序列号分发一个软件出去复制。

我尝试了处理器序列号和硬盘序列号,格式化和重新安装窗口后都改变了。

任何想法如何我可以得到一个不变的计算机序列号?

您可以使用WMI代码创build者 。 我想你可以有一个“键”(processorid,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); } 

Win32_Processor

用Peter Bromberg 在WMI中用C#检索硬件标识符

如果你需要一个唯一的ID ,你必须首先决定你的唯一的定义。 如果你想要/打算将其用于复制保护机制,那么使用简单的东西。 这是因为如果有人真的想使用你的软件,他会find一种方法来打破你的保护,给予足够的时间和技能。 如果是独特的硬件ID,只要考虑一下虚拟机,就会发现有可能欺骗任何东西,以至于有人会篡改你的软件。

没有太多可以从个人电脑,并认为它是在整个一生的独特性。 (硬件的更改很可能需要在某个时候重新生成ID)。如果您需要这样的事情,您应该使用可发送给客户的authenticationUSB Dongle进行调查。

如果您只需要一些不难获得的唯一标识符,您可以使用MAC地址(不可靠),操作系统序列号或域名和用户名,但所有这些都容易被伪造。 但是,如果您的主要目标是locking未经授权的人员,那么您将不会出售任何东西,因为如果难以安装,注册或从一台PC移动到另一台PC,则没有人愿意使用您的软件,尽pipe最后的考虑是部分和每个机器的授权许可。 (这可能会经常发生)

作为第一步,简单一点:使用一些简单的东西,在目标群体中不容易欺骗。 (例如,企业客户不容易欺骗域名和用户名,因为他们的PC正在执行策略的大环境中运行等)。

也许你可以locking它们,但这并不意味着他们会购买你的软件。 他们只是不会再使用它了。 你必须考虑的是有多less潜在客户不愿意或不愿意付钱,因为你使得你的程序变得如此复杂。

我会保持远离使用MAC地址。 在某些硬件上,当您重新启动时,MAC地址可能会更改。 我们在研究中很早就学会了不依靠它。

看看文章开发软件保护和授权 ,有一些关于如何devise和实施应用程序,以减less盗版指针。

强制免责声明和插件:我共同创立的公司生产OffByZero Cobalt授权解决scheme 。 所以,听到我build议外包你的授权,关注你的核心竞争力,你可能不会感到惊讶。

看看这篇文章 。 这是非常详尽的,你会发现如何提取各种硬件信息。

从文章引用:

要获取硬件信息,您需要创build一个ManagementObjectSearcher类的对象。

 using System.Management; ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from " + Key); foreach (ManagementObject share in searcher.Get()) { // Some Codes ... } 

上面的代码的关键是一个variables被replace为适当的数据。 例如,要获取CPU的信息,您必须用Win32_ProcessorreplaceKey。

编辑:我刚刚看到你的意思在C#中。 这是非托pipe代码的更好方法:

 ManagementClass oMClass = new ManagementClass ("Win32_NetworkAdapterConfiguration"); ManagementObjectCollection colMObj = oMCLass.GetInstances(); foreach(ManagementObject objMO in colMObj) Console.WriteLine(objMO["MacAddress"].ToString()); 

第二,Blindybuild议使用(第一个?)networking适配器的MAC地址。 是的,MAC地址可能被欺骗,但是这有副作用(你不需要在同一个networking中有两个MAC地址相同的PC),这是“你的平均海盗”不会只是为了能够使用你的软件。 考虑到没有100%的软件盗版解决scheme,MAC地址是一个很好的妥协,国际海事组织。

但是,请注意,当用户添加,replace或移除网卡(或者完全取代旧PC)时,地址会发生变化,因此请准备好帮助您的客户并在更改其硬件configuration时为其提供新的密钥。

是的,我们可以得到物理地址,唯一驱动器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"); } 

你不应该使用MAC,它的坏方法。 因为有些操作系统每天都在改变它。 我的expirience: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; } } 

你可以尝试从BIOS获取一些信息。 格式化后,这仍然有效。