得到唯一的机器ID

时间:2010-01-05 07:55:33

标签: c# system

我希望获得独特的不可更改的机器ID,如计算机的处理器序列号,用于分发软件而无需复制。

我尝试使用处理器序列号和硬盘序列号,这些序列号在格式化和重新安装Windows后都会发生变化。

知道如何获得不可更改的计算机序列号吗?

12 个答案:

答案 0 :(得分:14)

如果您需要唯一ID ,则必须先确定 unique 的定义。如果您希望/打算将它用于复制保护机制,那么使用简单的东西。这是因为如果有人真的想要使用你的软件,那么只要有足够的时间和技巧,他就会找到一种方法来打破你的保护。如果是唯一的硬件ID,只需考虑虚拟机,您就会发现可以欺骗任何东西,以免有人篡改您的软件。

您可以从PC上获取并且在整个生命周期中将其视为唯一性。 (硬件更改很可能需要在某个时刻重新生成ID。)如果您需要这样的内容,则应使用可以发送给客户的身份验证 USB Dongle 进行调查。

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

作为第一步,轻松一点:使用在目标群体中不容易欺骗的简单内容。 (例如,企业客户不容易欺骗域名和用户名,因为他们的PC在更大的环境中运行实施策略等。)只要忘记其他人,直到你拥有它。

也许你可以锁定它们,但这并不意味着它们会购买你的软件;他们只是不再使用它了。您需要考虑的是有多少潜在客户不愿意或不愿意支付,因为您使用该程序非常复杂。

答案 1 :(得分:14)

您可以使用WMI Code creator。我猜你可以组合使用“keys”(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的

Retrieving Hardware Identifiers in C# with WMI

答案 2 :(得分:11)

我会远离使用MAC地址。在某些硬件上,重新启动时MAC地址可能会发生变化。我们在研究期间很早就学会了不依赖它。

查看文章Developing for Software Protection and Licensing,其中有一些关于如何设计&实施应用程序以减少盗版。

强制性免责声明&插件:我共同创办的公司生产OffByZero Cobalt licensing solution。因此,听到我建议将您的许可外包,并且您可能不会感到惊讶。专注于你的核心竞争力。

答案 3 :(得分:4)

结帐this article。它非常详尽,您将找到如何提取各种硬件信息。

来自article

的引用
  

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

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

上面代码的密钥是一个用适当的数据替换的变量。例如,要获取CPU的信息,必须用Win32_Processor替换Key。

答案 4 :(得分:3)

编辑:我刚看到你在c#中的意思。以下是使用非托管代码的更好方法:

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

答案 5 :(得分:3)

是的,我们可以获得一个代码,它是物理地址,唯一驱动器ID,硬盘驱动器ID(卷序列),CPU ID和BIOS ID的组合。 示例(Full example):

//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");
    }

答案 6 :(得分:2)

我是第二个Blindy建议使用(第一个?)网络适配器的MAC地址。是的,MAC地址可能是欺骗性的,但这有副作用(你不希望在同一个网络中有两个具有相同MAC地址的PC),并且这是“你的平均盗版”不会只是为了能够做到这一点使用你的软件。考虑到没有100%的软件盗版解决方案,MAC地址是一个很好的妥协,IMO。

但请注意,当用户添加,替换或删除网卡(或完全替换旧PC)时,地址会发生变化,因此请准备好帮助您的客户并在他们更换硬件时为他们提供新密钥配置。

答案 7 :(得分:2)

你不应该使用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;
        }

    }

答案 8 :(得分:2)

也许最简单的方法是。 获取DeviceId Nuget包

并像

一样使用它
string deviceId = new DeviceIdBuilder()
.AddMachineName()
.AddMacAddress()
.AddProcessorId()
.AddMotherboardSerialNumber()
.ToString();

您可以个性化用于生成ID的信息

Github Project

答案 9 :(得分:0)

我知道有两种可能的解决方法:

  1. 获取系统的处理器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;
    }
    
  2. 获取系统的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;
    }
    

答案 10 :(得分:0)

以下site使用System.Management来完成相同的操作,这在控制台应用程序中是一种非常流畅的方式

答案 11 :(得分:-5)

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