【问题标题】:How do I generate a unique number for every computer? [duplicate]如何为每台计算机生成唯一编号? [复制]
【发布时间】:2017-04-03 10:41:08
【问题描述】:

我正在使用 C# 开发软件锁。我需要为每台计算机生成一个唯一编号。

我研究并决定使用 CPU 编号和硬盘驱动器编号作为每台计算机的唯一编号。

我的代码:

private string UniqID()
{
    ////////////////CpuID
    string cpuInfo = string.Empty;
    ManagementClass mc = new ManagementClass("win32_processor");
    ManagementObjectCollection moc = mc.GetInstances();

    foreach (ManagementObject mo in moc)
    {
        cpuInfo = mo.Properties["processorID"].Value.ToString();
        break;
    }

    ////////////////HDD ID
    string drive = "C";
    ManagementObject dsk = new ManagementObject(
        @"win32_logicaldisk.deviceid=""" + drive + @":""");
    dsk.Get();
    string volumeSerial = dsk["VolumeSerialNumber"].ToString();

    return volumeSerial + cpuInfo;
}

这行得通,但有一个问题! 当用户重新安装 Windows (OS) 并想要运行我的软件时,唯一编号已更改。 为什么重新安装 Windows 后唯一编号会发生变化? CPU 数量和硬盘数量是否取决于当前的 windows 安装?

【问题讨论】:

  • Get Hard disk serial Number 例如,或混合一些值。
  • @Qrchack 没有问题的内容不同
  • 没有什么是 100% 静态可靠的。例如,如果用户必须更换有故障的主板,主板序列号可能会发生变化。在系统中创建几个事物的哈希,并准备在某些条件下必须颁发替换许可证
  • 所以如果我改变了我的硬件,我就不能使用我合法获得的软件了?
  • @saeed 它没有不同。您需要一种唯一标识计算机的方法,至少在标题中(因为出于某种原因,您的标题问题和发布问题完全不同)。所以我给了你一个要考虑的事情清单,现在你称之为离题哈哈

标签: c# windows winforms


【解决方案1】:

您实际上拥有 MotherboardID、CPUID、磁盘序列号和 MAC 地址,根据经验,它们都不是 100%。

我们的数据显示

  • 磁盘序列号缺失 0.1 %
  • MAC 丢失 1.3 %
  • 主板 ID 缺失 30 %
  • CPUID 缺失 99 %

0.04% 的机器测试它们没有产生任何信息,我们甚至无法读取计算机名称。也许这些是虚拟 PC、HyperV 或 VMWare 实例之上的某种类型?

磁盘序列是最可靠的,但易于更改,mac 可以更改,如果添加设备驱动程序(hyperv、wireshark 等),根据应用的过滤可以更改。

主板和 CPUID 有时会返回占位符“NONE”等值。

您还应该注意,这些函数的调用速度可能非常慢(即使在快速的 PC 上也可能需要几秒钟),因此可能值得尽早在后台线程上启动它们,最好不要不想被他们挡住。

主板 ID

    private static void FetchMotherboardIdInternal()
    {
        try
        {
            ManagementScope scope = new ManagementScope("\\\\" + Environment.MachineName + "\\root\\cimv2");
            scope.Connect();

            using (ManagementObject wmiClass = new ManagementObject(scope, new ManagementPath("Win32_BaseBoard.Tag=\"Base Board\""), new ObjectGetOptions()))
            {
                object motherboardIDObj = wmiClass["SerialNumber"];
                if (motherboardIDObj != null)
                {
                    string motherboardID = motherboardIDObj.ToString().Trim();
                    Trace.WriteLine("MotherboardID = " + motherboardID);
                    if (IsValidMotherBoardID(motherboardID))
                    {
                        _motherboardID = motherboardID;
                    }
                }
            }
        }
        catch (System.Threading.ThreadAbortException)
        {
            throw;
        }
        catch (Exception ex)
        {
            Trace.TraceWarning("Failed to read MotherbaordID\r\n" + ex.Message);
        }
    }
    public static bool IsValidMotherBoardID(string value)
    {
        if (value == null)
            return false;
        string motherboardID = value.Trim();
        return !(   motherboardID.Replace(".", "").Replace(" ", "").Replace("\t", "").Trim().Length < 5 ||
                   motherboardID.ToUpper().Contains("BASE") ||
                   motherboardID.Contains("2345") ||
                   motherboardID.ToUpper().StartsWith("TO BE") ||
                   motherboardID.ToUpper().StartsWith("NONE") ||
                   motherboardID.ToUpper().StartsWith("N/A") ||
                   motherboardID.ToUpper().Contains("SERIAL") ||
                   motherboardID.ToUpper().Contains("OEM") ||
                   motherboardID.ToUpper().Contains("AAAAA") ||
                   motherboardID.ToUpper().Contains("ABCDE") ||
                   motherboardID.ToUpper().Contains("XXXXX") ||
                   motherboardID.ToUpper().Contains("NOT") ||
                   motherboardID.ToUpper().StartsWith("00000")
                );

    }

CPU ID

    private static void FetchCpuIdInternal()
    {
        try
        {
            using (ManagementClass mc = new ManagementClass("Win32_Processor"))
            {
                using (ManagementObjectCollection moc = mc.GetInstances())
                {
                    foreach (ManagementObject mo in moc)
                    {
                        if (mo.Properties["UniqueId"] != null && mo.Properties["UniqueId"].Value != null)
                        {
                            // only return cpuInfo from first CPU
                            Trace.WriteLine("CPU ID = " + mo.Properties["UniqueId"].Value.ToString());
                            _cpuID = mo.Properties["UniqueId"].Value.ToString();
                        }
                        mo.Dispose();
                    }
                }
            }
        }
        catch (System.Threading.ThreadAbortException)
        {
            throw;
        }
        catch (Exception ex)
        {
            Trace.TraceWarning("Failed to read CPUID\r\n" + ex.Message);
        }
    }

第一张卡的MAC地址

    private static void FecthMACAddressInternal()
    {
        try
        {
            using (ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration"))
            {
                using (ManagementObjectCollection moc = mc.GetInstances())
                {
                    if (moc != null)
                    {
                        foreach (ManagementObject mo in moc)
                        {
                            Trace.WriteLine(mo["Index"] + " Mac " + mo["Caption"] + " : " + mo["MacAddress"] + " Enabled " + (bool)mo["IPEnabled"]);
                            if (string.IsNullOrEmpty(_macAdderss))  // only return MAC Address from first card
                            {
                                if ( mo["MacAddress"] != null && mo["IPEnabled"] != null && (bool)mo["IPEnabled"] == true)
                                {
                                    _macAdderss = mo["MacAddress"].ToString();
                                }
                            }
                            mo.Dispose();
                        }
                    }
                }
            }
        }
        catch (System.Threading.ThreadAbortException)
        {
            throw;
        }
        catch (Exception ex)
        {
            Trace.TraceWarning("Failed to read DiskID\r\n" + ex.Message);
        }
        if (_macAdderss != null)
            _macAdderss = _macAdderss.Replace(":", "");
    }

驱动器序列号

    /// <summary>
    /// return Volume Serial Number from hard drive
    /// </summary>
    /// <param name="strDriveLetter">[optional] Drive letter</param>
    /// <returns>[string] VolumeSerialNumber</returns>
    public static string GetVolumeSerial(char driveLetter)
    {
        try
        {
            using (ManagementObject disk = new ManagementObject("win32_logicaldisk.deviceid=\"" + driveLetter + ":\""))
            {
                if (disk == null)
                    return null;
                disk.Get();
                object diskObj = disk["VolumeSerialNumber"];
                if (diskObj != null)
                    return diskObj.ToString();
            }
        }
        catch (System.Threading.ThreadAbortException)
        {
            throw;
        }
        catch (Exception ex)
        {
            Trace.TraceWarning("Failed to read DiskID\r\n" + ex.Message);
        }

        try
        {
            uint serialNum, serialNumLength, flags;
            StringBuilder volumename = new StringBuilder(256);
            StringBuilder fstype = new StringBuilder(256);

            bool ok = GetVolumeInformation(driveLetter.ToString() + ":\\", volumename, (uint)volumename.Capacity - 1, out serialNum, out serialNumLength, out flags, fstype, (uint)fstype.Capacity - 1);
            if (ok)
            {
                return string.Format("{0:X4}{1:X4}", serialNum >> 16, serialNum & 0xFFFF);
            }
        }
        catch (System.Threading.ThreadAbortException)
        {
            throw;
        }
        catch (Exception ex2)
        {
            Trace.TraceWarning("Failed to read DiskID\r\n" + ex2.Message);
        }

        return null;
    }


  [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    static extern bool GetVolumeInformation(string Volume, StringBuilder VolumeName, uint VolumeNameSize, out uint SerialNumber, out uint SerialNumberLength, out uint flags, StringBuilder fs, uint fs_size);

【讨论】:

  • 感谢您的代码,请问您从哪里提取“GetVolumeInformation”?
  • 它是一个 DllImport("kernel32.dll".... 我已将代码添加到答案中
【解决方案2】:

使用System.Management,您可以提取所有硬件信息。有了这个,你可以从这个值创建一个 ID,meaby 一个加密的 id 并保存它。

这是一个参考:Link

我使用 MAC 地址、主板 ID 并且工作正常。

希望对你有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-25
    • 1970-01-01
    • 2012-02-19
    • 2017-04-06
    • 1970-01-01
    • 2016-05-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多