有没有人知道比较两个.NET程序集以确定它们是否是从"相同"源文件构建的方法?
我知道有一些差异实用程序可用,例如Reflector的插件,但我对查看GUI中的差异不感兴趣,我只是想要一种自动方式来比较二进制文件的集合,看看它们是否是从相同(或等效)的源文件.我知道多个不同的源文件可以产生相同的IL,并且意识到该过程只对IL的差异敏感,而不是原始源.
仅仅比较两个程序集的字节流的主要障碍是.NET包含一个名为"MVID"(模块版本标识符)的程序集.这似乎对每个编译都有不同的值,因此如果您构建相同的代码两次,则程序集将有所不同.
一个相关的问题是,是否有人知道如何强制MVID为每个编译相同?这将避免我们需要具有对MVID值的差异不敏感的比较过程.一致的MVID将是更可取的,因为这意味着可以使用标准校验和.
这背后的背景是,在我们被允许发布到Production之前,第三方公司负责独立审核和签署我们的版本.这包括查看源代码.他们希望独立确认我们提供的源代码与我们之前构建,测试并且当前计划部署的二进制文件相匹配.我们正在寻找一个允许它们从我们提供的源中独立构建系统的过程,并将校验和与我们测试的二进制文件的校验和进行比较.
BTW.请注意,我们正在使用持续集成,自动构建,源代码控制等.该问题与内部缺乏对源文件进入给定构建的控制无关.问题在于,第三方负责验证我们提供的来源是否与我们测试过并计划投入生产的二进制文件相同.他们不应该信任我们的任何内部系统或控件,包括构建服务器或源代码控制系统.他们所关心的只是获取与构建相关的源,自己执行构建,并验证输出是否与我们所说的部署相匹配.
比较解决方案的运行速度并不是特别重要.
谢谢
更新:我现在有了一个解决方案,我对此更加满意,虽然没有解决我提出的所有问题,但它确实让我们明白了.我已经更新了自己的答案以反映这一点.
原始问题
给定App域,Fusion(.Net程序集加载器)将针对给定程序集进行探测,有许多不同的位置.显然,我们认为这个功能是理所当然的,因为探测似乎嵌入在.Net运行时Assembly._nLoad内部(内部方法似乎是反射加载时的入口点 - 我假设隐式加载可能由同一个底层覆盖算法),作为开发人员,我们似乎无法访问这些搜索路径.
我的问题是我有一个组件可以执行大量动态类型解析,并且需要能够确保在开始工作之前预先加载给定AppDomain的所有用户部署的程序集.是的,它减慢了启动速度 - 但我们从这个组件中获得的好处完全超出了这一点.
我已经编写的基本加载算法如下.它深扫描任何.dll文件(.EXE文件被排除一组文件夹的那一刻),并使用Assembly.LoadFrom如果它的AssemblyName不能在集已经加载到AppDomain中组件可以找到加载DLL(这实现效率低下,但可以在以后进行优化):
void PreLoad(IEnumerable<string> paths)
{
foreach(path p in paths)
{
PreLoad(p);
}
}
void PreLoad(string p)
{
//all try/catch blocks are elided for brevity
string[] files = null;
files = Directory.GetFiles(p, "*.dll", SearchOption.AllDirectories);
AssemblyName a = null;
foreach (var s in files)
{
a = AssemblyName.GetAssemblyName(s);
if (!AppDomain.CurrentDomain.GetAssemblies().Any(
assembly => AssemblyName.ReferenceMatchesDefinition(
assembly.GetName(), a)))
Assembly.LoadFrom(s);
}
}
Run Code Online (Sandbox Code Playgroud)
使用LoadFrom是因为我发现使用Load()会导致Fusion加载重复的程序集,如果它在探测它时,它找不到从它希望找到它的地方加载的程序集.
因此,有了这个,我现在要做的就是获得Fusion在搜索程序集时将要使用的搜索路径的优先顺序(从高到低)的列表.然后我可以简单地遍历它们.
GAC与此无关,我对Fusion可能使用的任何环境驱动的固定路径不感兴趣 - 只有那些可以从AppDomain收集的路径,其中包含为应用程序明确部署的程序集.
我的第一次迭代只使用了AppDomain.BaseDirectory.这适用于服务,表单应用程序和控制台应用程序.
但是,它不适用于Asp.Net网站,因为至少有两个主要位置 - AppDomain.DynamicDirectory(其中Asp.Net放置动态生成的页面类和Aspx页面代码引用的任何程序集),以及然后是站点的Bin文件夹 - 可以从AppDomain.SetupInformation.PrivateBinPath属性中找到它. …
在Windows 2003和Windows XP中,您可以右键单击程序集(.dll)转到属性,单击版本选项卡,然后您将看到3个不同的版本号:程序集版本,文件版本和产品版本.
如果您使用相同的文件并在Windows 2008中查看其属性,则只能看到文件版本和产品版本.
有没有办法在Windows Vista和更新版本(没有第三部分工具)中查看.NET程序集的程序集版本?
我在Visual Studio中有一个相当大的解决方案.有没有办法一次性更新解决方案中所有程序集的主要/次要版本号?
我想解析.NET 3.5中的程序集限定名称.特别是,组件本身不可用,它只是名称.我可以想到很多方法可以手动完成,但我想我可能会遗漏一些在系统库中执行此操作的功能.有什么建议吗?
当我尝试运行一个简单的程序来访问oracle时,我收到了这条消息
无法加载文件或程序集'Oracle.DataAccess,Version = 2.111.7.20,Culture = neutral,PublicKeyToken = 89b483f429c47342'或其依赖项之一.该系统找不到指定的文件.
我检查了\ windows\assembly它在那里,但它不在GAC(gacutil -l)中.我无法添加到GAC中(gacutil -i [path]我得到'未知错误'.
任何人都有同样的体验?
我的应用程序包含三个程序集:一个引用几个DLL的EXE.DLL对我的应用程序是私有的 - 它们仅由此可执行文件使用.
这些集会是否应该有一个强有力的名字?
FxCop建议他们应该 - 对于它目前生成的所有程序集:
CA2210:使用强名称密钥对<assembly>进行签名.
但是,这个建议说:
通常,您应该避免强命名应用程序EXE程序集.
和
您可能希望避免使用应用程序专用的强命名组件.
我应该给这些集会一个强有力的名字吗?在这种情况下这样做(或不这样做)有什么好处?
编辑:
看几个具有类似结构的应用程序,似乎没有就此问题达成共识.Paint.NET和Crack.NET的二进制文件没有强名称,而.NET Reflector和Snoop的二进制文件则没有.
有趣的是,使用Expression套件,Microsoft采用了后一种方法:例如,在Expression Blend中,他们选择对Blend.exe和随附的DLL(例如Microsoft.Expression.Blend.dll)进行强名称签名.
似乎我不太可能得到第一个问题的简单答案:"我应该给这些集会一个强有力的名字吗?".但是,我的第二个问题仍然存在:
在这种情况下,强名称签名二进制文件是否有任何好处?或者,不这样做会有什么好处吗?
编辑2:
如果无论如何都没有压倒性的理由,我倾向于给我的集会一个强有力的名字.因此,我对是否有人可以扩展(从第一个链接)感兴趣:
"强命名可能会使管理依赖项变得更加困难,并为私有组件增加不必要的开销."
.net程序集的大小是否会影响性能?Windows窗体/ Web表单项目中的程序集数量如何?
假设我们有一个具有以下结构的解决方案:
编译Project.UI时,VS非常聪明,可以将Project.DAL.dll复制到输出目录,但是它不够聪明,我想要将Oracle.DataAccess复制到输出目录以及分发给客户端.
任何人都可以解释为什么会这样吗?是因为它在GAC中看到Oracle.DataAccess并假设客户端也会在GAC中拥有它吗?
这并不是什么大不了的事,但每次添加新的程序集引用时都有点烦人,我必须记住将其设置为复制本地并添加项目以在我的构建脚本中复制它.
我目前正在为我们公司的其他应用程序进行服务器控制,以便与WCF服务进行交互.每次我更改代码更改并重新编译控件时,我都会将AsseemblyInfo.cs中的AssemblyVerison和AssemblyFileVersion类增加一个.例如,我的最新版本从1.0.07.0到1.0.08.0.
当使用应用程序通过复制bin目录中的最新文件并尝试编译来更新文件时,它们会收到以下错误:
命名空间"MyNamespace"中不存在类型或命名空间名称"MyControl"(您是否缺少程序集引用?)
为了解决此错误,他们必须删除当前引用并重新添加引用.
有没有办法更新服务器控件而无需删除和重新添加引用?
我并不强烈命名服务器控件.
@JPunyon - 你的意思是让消费者应用程序将服务器控制项目添加到他们的解决方案中吗?
assemblies ×10
.net ×7
reflection ×2
c# ×1
checksum ×1
il ×1
msbuild ×1
oracle ×1
parsing ×1
performance ×1
reference ×1
strongname ×1
windows-7 ×1