- 这些库是你的,我是说,是你的代码吗?
- 它们是由您的安装人员安装的,还是独立安装的,您只需检查它们?
如果您可以通过任何方式监督它们在目标机器上的初始安装,您可以使用普通的旧 DLL 资源做一些穷人的水印。
将包含您自己内容的二进制资源附加到已安装的每个版本的 DLL,然后检查该文件。如果您在每个代码中嵌入 public static readonly class Something{ public static SomeData MyImportantInformation = ...; } 并在运行时读取它,或者您将 [Attributes] 与某些类上的数据一起使用并通过反射读取它们,那就更棒了——但使用二进制资源有两个微小的优势:
- 您可以在 DLL 在构建之后从 DLL 添加/删除资源(有点像使用 ILMerge 工具)
- 您可以像从托管代码中一样轻松地从本机代码中读取资源,并且要读取它们,您可以以非常有限且节省资源的方式加载 DLL
请注意,我的意思是“低级资源”,例如 Manifest,它通常位于插槽 #0 上的资源,或 .exe/.dll 图标。
关于二进制资源:
http://www.codeproject.com/Articles/4221/Adding-and-extracting-binary-resources
以及更易于使用的托管嵌入式资源:
http://keithelder.net/2007/12/14/how-to-load-an-embedded-resource-from-a-dll/
https://stackoverflow.com/a/7978410/717732
您可以在构建脚本中添加/修改资源,以确保发布的每个版本都添加了不同/正确的信息。当然,如果您控制构建过程,那么您也可以启动前面提到的 ILmerge 以将任何内容放入任何 DLL 中。虽然大部分都可以工作,但总的来说,我认为这是一种矫枉过正,如果做得不正确的话如果它在签名后修改 DLL,则会破坏任何安全签名。它必须在它之前完成..
如果您控制构建过程,您可以将必要的版本信息作为类静态数据或简单地作为程序集级别的属性放入代码中,或者 (...)
或者你为什么不直接使用版本号来区分版本? :) IE。 semantic versioning?
另一方面,如果您正在使用非您的 DLL,并且您无法控制它们的部署,那么您的处境就很艰难。正如其他人所说,编译器在编译过程中可能会应用许多不同的技巧,但是 - 请注意 - 他们对编译后的代码有一些法律和逻辑限制。
“逻辑”约束示例:
- 他们可能会改变说明,但可能不会改变整体含义和(副作用)
- 他们可能会改变代码和数据布局/结构,但不会改变处理它们的算法
等等
“法律”限制示例:
- 不允许删除任何公共符号(公共 = 其他代码模块可见,即在 .Net 中涵盖:公共和受保护,有时甚至是内部和私有)
- 不允许更改任何公共符号的名称
- 不允许他们更改任何公共符号的签名
等等
现在,如果您将自己仅限于此类信息,您可以以一种有机会独立于编译器和平台的方式收集/计算任何代码的哈希值/签名。您不会得到相同或不同的明确答案,但您会了解它们的可能性有多大。
举个最简单的例子:通过反射加载 DLL 并扫描所有类的公共和非公共成员名称。然后,要么计算该字符串集的哈希值,要么只使用整个字符串集,我可能最多以千字节计。如果对代码进行了较大的更改,几乎可以肯定会添加或删除某些字段/方法。对于较小的更改,您还可以扫描方法的签名:添加参数列表和参数类型并将值返回到池中。更多的工作和更多检测到变化的可能性。
对于一个重要的更改:您可以尝试扫描方法的 ILCode 并检测其中的结构。编译器可能会内联,有时会删除方法/循环/等,但会保留整体结构。特定的代码块在这里或那里执行 n 次,分支在它们的位置但可能交换边等。但是,检测控制结构并不容易,比较代码更加困难。对于某些代码,它可能会给你一个“完全相同”的明确答案,但很多时候你会得到“不一样”,即使它们是。该主题的一些关键字是......重复或抄袭检测器。这就是对此类事物的研究的开始:) 参见 ie。 https://stackoverflow.com/questions/546487/tools-to-identify-code-duplications 虽然我不知道提到的工具是扫描代码还是“字节”..