不应该在本地复制本地的程序集

时间:2013-02-17 17:21:10

标签: c# visual-studio-2010

这是我的示例场景。我有一个Console应用程序和一个类库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会在其输出目录中显示 not 。好。现在我在我的控制台应用程序中引用libraryA dll。对libraryA dll的引用是“copy local = true”。现在,当我构建控制台应用程序时,Oracle.DataAcess.dll 显示在控制台应用程序的输出目录中。但是,似乎这种方式的唯一DLL是Oracle 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并设置copy local = false。即使这样做,libraryB也不会复制到控制台应用程序的输出目录中。当然,在这种情况下,程序会爆炸,因为它找不到库B,但至少Visual Studio尊重copy local flag = false。这个愚蠢的Oracle DLL有什么不同?

哦,还有一件事很有趣。如果在我的控制台应用程序中,我显式地添加对Oracle.DataAccess.dll的引用,并说复制local = false,然后它不会显示在输出目录。似乎有点搞笑,在输出目录中显示DLL,我必须引用它:)

修改

另一个线索。为了折磨开发人员,Oracle没有为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复制到你的输出目录,从而保证你的应用程序将爆炸。 :)

2 个答案:

答案 0 :(得分:4)

通过不引用它,你让它使用隐式规则。好吧,这里的隐式默认值是“将其复制到本地”,因为大多数 dll不在GAC中。 IDE有一个疯狂的默认概念,即“让它工作”,这意味着“假设它不会出现在GAC中”。

如果你想使用明确的规则,那么是:你需要告诉它你想要什么。你这样做的方法是添加一个引用,然后设置你想要的选项。

答案 1 :(得分:0)

在我正在处理的解决方案中对似乎是同一个问题的大量调查之后,我们发现这个问题似乎是由.NET 4.5版本引入的新检查引起的,如上所述here:在构建时,现在正在检查引用以确保它们的处理器类型与项目的类型相匹配。

虽然之前我们在构建日志中没有看到任何此类错误,但在受影响的计算机上,我们现在看到一条消息,指示项目正在为MSIL构建并且DLL是为x86构建的 - 而不是为一个为其构建的DLL所有CPU,第三方创建者为x86和x64提供了两个独立的DLL,这两个DLL都在我们的GAC中。在引入此检查之前,系统将使用GAC中的DLL并选择适当的版本,但似乎在安装.NET 4.5之后,构建过程确定GAC中的任何版本都不可接受,因此它会引入本地副本。

我们无法找到任何方法来禁用此行为,因此我们的解决方案选项必须是添加后期构建事件以删除本地副本,或者(如问题中所述)将问题DLL的引用添加到引用我们的“库A”的所有项目,然后将这些引用设置为“copy local = false”,这似乎也防止将不工作的本地版本复制到输出中。