如何在Delphi中生成唯一的机器序列号?

7

我有一个问题,如何在Delphi中生成唯一的机器序列号?我尝试使用主板或处理器的ID来实现这一点,但不幸的是它不被支持。分区序列号等会掉落,因为它们在格式化后会发生变化。我正在寻找一些在格式化后不会改变的东西。有人有什么想法吗?


请查看以下问题:https://dev59.com/IErSa4cB1Zd3GeqPYKvT - RRUZ
3
你是想要“生成”一个序列号,还是想知道已有的各种序列号该如何“发现”? - Rob Kennedy
如果您的用户不总是在同一台机器上,会发生什么情况?例如,当他/她在VDI(虚拟桌面)环境中工作时? - Remko
我猜答案取决于你为什么需要这个信息,也就是你打算用这个信息做什么。 - Alex
我在这里看到很多错误的答案。指南是永远不要使用“软”ID /编号(如mac、wmi、注册表、卷ID)。只使用真正的硬件写入(只读!)ID。 - Gabriel
7个回答

6

JCL 库中,有几个与此主题非常有用的函数:

function CPUID: TCpuInfo;
function GetMacAddresses(const Machine: string; const Addresses: TStrings): Integer;
function GetVolumeSerialNumber(const Drive: string): string;
function GetBIOSName: string;

4
您需要的实际上是某种“硬件指纹”,而不是“序列号”。这种方法的问题在于它并不是100%可靠。证明:微软无法找到一种适当限制OEM软件仅限于任何单个计算机的方法,您实际上可以在一段时间后将OEM许可证重新安装到新计算机上!一旦您同意没有完美解决方案,您可以查看选项并尝试获得足够好的东西。
对于我的应用程序,我基于GetSystemInfo、GetVolumeInformation返回的信息以及(对于'C:'分区)来自HKLM \ HARDWARE的一些注册表键的选择创建指纹(实际上有很多注册表键,除了usb、键盘和鼠标之外的所有内容)。我从注册表中读取硬件信息,因为Windows应用程序实际上无法直接访问硬件(DOS风格的方法行不通),而且我没有时间找出确定许多不同设备的与硬件相关的信息的方法。
我的方法具有以下缺点:
- 使用由格式设置的分区序列号。格式化会清除磁盘并更改指纹。 - 使用有关已安装驱动程序的信息。更新驱动程序可能会更改指纹!将卡从一个PCI端口移动到另一个端口可能会更改指纹。
尽管考虑到所有这些变化的信息,但我仍然会遇到冲突:大约1/1000台计算机!这里有几个因素起作用:
- 大型OEM使用相同的硬件构建许多计算机。他们还克隆HDD以加快软件安装,因此不同的PC可能会获得相同的分区序列号。 - 我从所有信息中构建了一个非常短的哈希,足够短,以便人们可以在电话中向我读取它而没有太多错误。
这个系统适合我,但如果您希望重新安装后重新识别计算机,则无法为您工作。

2
我认为如果您添加了主板上以太网适配器的MAC地址(假设有一个),那么您应该能够消除冲突。 - Chris Thornton
你有你的解决方案的任何示例或测试代码吗? - peiman F.
卷标识(Volume ID)是完全不可靠的,因为它可以非常容易地更改。 - Gabriel

3
你可以测试GLibWMI,它可以提取Windows上多个组件的信息。
它是免费的并且包含源代码。您可以在我的网站Sourceforge上找到它。

alt text http://img175.imageshack.us/img175/1250/imagen344.png

包括BIOSInfo、DiskInfo、ProcessorInfo等组件。

使用这三个组件,您可以获得如下信息:

alt text http://img690.imageshack.us/img690/6006/imagen349.png

你可以在这里找到GenericDemo(所有组件)的BIN/EXE;使用这些组件,你可以测试所有可检索到的信息。

我发现这个库在检索ID方面非常不可靠。该库提供的是硬件信息而不是硬件ID。 - Gabriel

1

我在好早的DOS时代也遇到了类似的问题。我发现安装的硬件,例如视频卡、磁盘控制器、串行端口等ROM可以直接访问,因为它们是映射到内存中的。这意味着我能够创建一个已安装硬件列表,并用它生成一个“序列号”,唯一地标识每台电脑(直到硬件设置被更改)。我相信今天也有类似的可能性。

如果您想采用这种方法,请查看http://duartes.org/gustavo/blog/post/motherboard-chipsets-memory-map

敬礼

  • Frank

一个 Delphi 应用程序真的可以访问任意内存吗?据我所知,Windows 应用程序不应该能够访问操作系统没有专门为它们分配的内存! - Cosmin Prund

1

通常使用网络适配器的MAC地址,有多种方式来查询MAC地址(在Delphi中),但最简单/最清晰的方法可能是使用GetAdaptersInfo API。


2
请注意,无线网卡可能会随意出现/消失,当用户关闭一张卡时,Windows会将其从列表中删除,并且顺序不总是相同的。此外,如果用户有更改硬件设置的权限,则可以更改MAC地址。 - user160694
MAC地址或卷标ID是完全不可靠的,因为它们可以轻松更改(只需进行谷歌搜索,您将看到许多免费工具正在执行此操作)。WMI也是如此。 - Gabriel

1

这里有一个简单的解决方案

  • 生成一个GUID
  • 将GUID值保存在注册表中
  • 使用GUID值作为序列号

如果您担心安全问题,请对(GUID + 一些秘密数据)进行哈希处理


这不会满足OP的需求,因为您永远无法使用它来识别机器。即,如果您正在尝试许可一些软件,以便它只能在“此计算机”上运行,则无法生成新的GUID(明天,明年或在重新安装Windows之后等)并获得相同的GUID以识别该机器。即使是1毫秒后,它看起来也像是另一台PC。 - Chris Thornton
MAC ID或Volume ID是非常不可靠的,因为它们可以很容易地更改(只需进行谷歌搜索,您会看到许多免费工具正在执行此操作)。WMI也是如此。但是注册表解决方案????????不是一个解决方案!!! - Gabriel

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接