当不应该时,程序集被复制到本地。
当不应该时,程序集被复制到本地。
这是我的一个示例场景。我有一个控制台应用程序和一个类库dll(称之为LibraryA)。LibraryA dll引用了Oracle.DataAccess.dll版本4.112.2.0。Oracle DLL在GAC中。LibraryA中对Oracle DLL的引用为“Copy Local = false”。 到目前为止一切顺利。如果您构建libraryA dll,则Oracle.DataAccess.dll不会出现在其输出目录中。好的。现在我在我的控制台应用程序中引用LibraryA dll。对libraryA dll的引用为“复制本地=true”。现在,当我构建控制台应用程序时,Oracle.DataAcess.dll确实显示在控制台应用程序的输出目录中。但是,似乎唯一的行为是Oracle dll的DLL。这里是LibraryA的完整代码
public void Foo() { Oracle.DataAccess.Client.OracleConnection c = new Oracle.DataAccess.Client.OracleConnection(); WebMatrix.WebData.OAuthAccountData x = new WebMatrix.WebData.OAuthAccountData("asd", "asd"); DevExpress.Web.ASPxCallback.ASPxCallback cvv = new DevExpress.Web.ASPxCallback.ASPxCallback(); }
WebMatrix和DevExpress也像Oracle DLL一样在GAC中。但是,这两个DLL都不会输出到输出目录中,只有Oracle dll。为什么?这里发生了什么?
就此而言,您可以创建另一个类库,称其为libraryB,不要将libraryB放入GAC,从LibraryA引用LibraryB并设置复制本地=false。即使这样做,libraryB也不会复制到控制台应用程序的输出目录中。当然,在这种情况下,程序会崩溃,因为找不到library B,但至少Visual Studio尊重复制本地标志=false。这个愚蠢的Oracle DLL有什么不同?
哦,还有一件有趣的事情。如果在我的控制台应用程序中,我明确添加了对Oracle.DataAccess.dll的引用,并说复制本地=false,则它不会出现在输出目录中。好像不得不引用它才能使DLL不显示在输出目录中:)
编辑:
另一个线索。甲骨文为了折磨开发者,没有为AnyCPU构建一个DLL。他们有一个x86和一个x64版本。在我的情况下,我正在引用x86版本并为AnyCPU构建。但是,如果我为x86构建(以匹配oracle dll),那么Oracle DLL将不会复制到输出目录中。当使用AnyCPU进行构建时,MSBUILD会发出以下警告:
“警告MSB3270:正在构建的项目的处理器架构“MSIL”与引用“Oracle.DataAccess,Version = 4.112.2.0,Culture = neutral,PublicKeyToken = 89b483f429c47342,processorArchitecture = x86”“x86”之间存在不匹配。此不匹配可能导致运行时故障。请考虑通过Configuration Manager更改项目的目标处理器架构以对齐项目和引用之间的处理器架构,或依赖于具有与项目的目标处理器架构相匹配的处理器架构的引用。”因此,它几乎看起来像Msbuild最终决定,好吧,你有不匹配,所以让我继续将此dll复制到您的输出目录,从而保证您的应用程序将崩溃。 🙂
在对我所工作的一个解决方案中似乎相同问题进行了充分调查后,我们发现这个问题似乎是由于.NET 4.5版本发布时引入了一个新的检查引起的,如这里所提到的:在编译时,现在检查参考项来确保其处理器类型与项目的处理器类型相匹配。
之前在构建日志中没有看到任何这样的错误,在受影响的机器上,我们现在看到一个消息表明项目正在为MSIL构建,而DLL是为x86构建的-而不是提供一个为所有CPU构建的DLL,第三方创建者提供了两个单独的DLL,一个为x86,一个为x64,两者都在我们的GAC中。在引入此检查之前,系统将使用来自GAC的DLL并选择适当的版本,但似乎在安装.NET 4.5后,构建过程确定GAC中的任何版本都不可接受,因此正在拉入一个本地副本。
我们无法确定任何禁用此行为的方法,因此我们的解决选项要么是只需添加后构建事件以删除本地副本,要么是(如问题中所提到的)向引用我们的"Library A"的所有项目添加对问题DLL的引用,然后将这些引用设置为"copy local = false",这似乎也可防止将不起作用的本地版本复制到输出中。