程序集应在本地复制';不要

本文关键字:不要 复制 程序集 | 更新日期: 2023-09-27 17:59:50

这是我的示例场景。我有一个控制台应用程序和一个类库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的输出目录中不会出现。好的。现在我在控制台应用程序中引用库A 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也在GAC中,就像Oracle DLL一样。但是,这两个dll都没有输出到输出目录,只有Oracle dll为什么?这里发生了什么?

就这一点而言,您可以创建另一个类库,称之为libraryB,不要将libraryB放在GAC中,从LibraryA引用libraryB,并设置copy local=false。即使这样做,libraryB也不会复制到控制台应用程序的输出目录中。当然,在这种情况下,程序会因为找不到库B而崩溃,但至少Visual Studio尊重复制本地标志=false。这个愚蠢的Oracle DLL有什么不同?

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

编辑

另一条线索。为了折磨开发人员,Oracle没有为AnyCPU构建一个DLL。它们有x86和x64版本。在我的例子中,我引用的是AnyCPU的x86版本和构建。但是,如果我为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复制到你的输出目录,从而保证你的应用程序会爆炸",因为大多数dll都不在GAC中。IDE有一个疯狂的想法,默认为"让它工作",这意味着"假设它不会在GAC"。

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

程序集应在本地复制';不要

在对我所研究的解决方案中的相同问题进行了大量调查后,我们发现这个问题似乎是由的发布时引入的新检查引起的。NET 4.5,正如这里提到的:在构建时,现在正在检查引用,以确保它们的处理器类型与项目的处理器类型匹配。

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

我们还无法确定任何禁用此行为的方法,因此我们的解决方案必须是添加一个生成后事件以删除本地副本,或者(如问题中所述)将对问题DLL的引用添加到引用我们的"库a"的所有项目,然后将这些引用设置为"copy local=false",这似乎也防止了将不工作的本地版本复制到输出中。