ChatGPT解决这个技术问题 Extra ChatGPT

引用 DLL 文件未与部署项目一起复制到 bin,导致错误

我们的 Web 应用程序项目中引用了几个外部 DLL 文件。我们有一个用于在托管服务器上安装的部署项目。当我们使用 .NET 3.5 和 Visual Studio 2008 时,DLL 文件被复制到 bin 文件夹中。由于我们已升级到 .NET 4 和 Visual Studio 2010,这种情况不再发生,并且由于找不到引用,我们收到了服务器错误。

CopyLocal 设置为 true,我在 web.config 中找不到任何内容,这表明这是在其他地方设置的。


P
Peter Mortensen

Visual Studio 2010 中存在一个错误。默认情况下,解决方案文件中的 XML 如下所示:

<Reference Include="DevExpress.SpellChecker.v11.1.Core,
           Version=11.1.5.0,
           Culture=neutral,
           PublicKeyToken=b88d1754d700e49a,
           processorArchitecture=MSIL">
<HintPath>..\References\DevExpress.SpellChecker.v11.1.Core.dll</HintPath>
</Reference>

而 MSBuild 期望在下面这样做,以便 DLL 文件将包含在部署中:

<Reference Include="DevExpress.SpellChecker.v11.1.Core,
           Version=11.1.5.0,
           Culture=neutral,
           PublicKeyToken=b88d1754d700e49a,
           processorArchitecture=MSIL">
<HintPath>..\References\DevExpress.SpellChecker.v11.1.Core.dll</HintPath>
<Private>True</Private>
</Reference>

诀窍是将 Copy Local 设置为 False保存项目,然后将其重置为 True - 再次保存。这正确地包括了 MSBuild 尊重的 Private 节点。

似乎 Visual Studio 2010 中未包含的专用节点 (Copy Local) 的默认值为 True,而 MSBuild 将该缺失节点读取为 False


VS2012中仍然存在错误。它确实应该修复,我花了一段时间才找到这个解决方案。
今天发现这个 CopyLocal 技巧并不会影响当前项目上面的引用。例如,我有一个在 GAC 中引用 some.dll 的项目实体。如果我如上所述对 some.dll 强制 CopyLocal=true,一切似乎都很好 - some.dll 被复制到实体的 bin 文件夹中。但是,如果我在某些项目 Services 中引用 Entities 项目并希望将 some.dll 复制到 Services\bin,则不会发生 - Services 项目忽略了 Entities 项目的 CopyLocal=true 并仍然从广汽。使用 VS2012。
虽然这修复了项目文件,但 MSBuild.exe 从命令行仍然不遵守此设置,因此任何类型的自动构建脚本都不会正确构建代码(例如,引用的项目引用 dll 不会在 bin 目录中)
当我配置 nuGet 以提供缺少的包时,我遇到了 VS2013。我发现成功解决此问题的唯一方法是将对缺少的程序集的引用添加到我的起始项目中。耶奇。
我刚刚在 VS2015 中遇到了同样的问题。仅供参考,此答案中提到的 XML 引用存储在项目文件中,而不是解决方案文件中。
s
stevie_c

我遇到了同样的问题,我没有添加“BeforeBuild”步骤,而是创建了一个简单的测试

    [TestMethod]
    public void ReferenceAssemblyThatDoesNotCopyToBuildFolder()
    {
        Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler referenceThisButDoNotUseIt = null;
    }

并修复了错误无法解决类型“Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler ...”


P
Peter Mortensen

我的部署项目发生了一些奇怪的事情。当我看到它没有检测到依赖项时,我删除了主要输出并重新添加了它。

依赖项现在显示并在安装时放置在 bin 文件夹中。


伟大的。只有一个问题:您是如何发现它没有检测到依赖关系的?这是哪个选项?请详细说明。谢谢
在我的部署项目中,有一个检测到的依赖项文件夹。它在那里检测到的唯一东西是 .net 框架。您可以右键单击此文件夹并单击“刷新依赖项”,但即使这对我也不起作用。当我重新添加主要输出时,检测到依赖关系。这很奇怪,是在 vs2008 和 vs2010 之间的转换过程中造成的。我会说这是一个错误,但事实上我所有的其他部署项目都完美地转换了。在一天结束时,我不知道发生了什么。
我在 vs.net 2010 中新创建的解决方案遇到了同样的问题,所以这不是升级问题。正如您所说,删除主要输出和读取似乎可以解决问题。
有人可以澄清“删除主要输出”是什么意思吗?
P
Peter Mortensen

我只是遇到了同样的问题,并想分享我的发现,因为它可能对某人有所帮助:

就我而言,原因是在安装某些第三方应用程序期间,程序集安装在 GAC 中。

如果 DLL 文件在 GAC 中,编译器不会费心将其复制到目标文件夹,除非您使用 Junto 提到的项目文件中的“私有”节点将其专门标记为“复制本地”。

问题是,如果您不添加该节点,并且您在一台机器上开发并在另一台机器上构建,并且 DLL 文件仅在构建机器的 GAC 中,则没有私有节点的默认行为将导致文件要在开发机器上正确复制,而不是在构建机器上。

更大的问题是,如果没有直接引用 DLL 文件,但项目引用了第二个项目,该项目又引用了 DLL 文件。在这种情况下,您不能在项目中将 DLL 文件标记为“本地复制”,因为它没有被它引用。因此,如果 DLL 文件存在于 GAC 中 - 它不会被复制到您的输出文件夹中。

这种情况的可能解决方案是:

从 GAC 卸载 DLL 文件

在最终项目中添加对 DLL 文件的直接引用

使用新的强名称重新签署 DLL 文件,这将与 GAC 中的 DLL 文件区分开来。


P
Peter Mortensen

我遇到了完全相同的问题。我们有一个引用 EnterpriseLibrary 的 Visual Studio 2008 项目。当我们使用 TFS 和我们的 Web 部署项目运行我们的集成构建时,所有的 DLL 文件都会被复制过来。当我们升级到 Visual Studio 2010、TFS 2010 和 WDP 2010 时,一些 DLL 文件丢失了。奇怪的是,这只会发生在某些 DLL 文件中,而不会发生在其他文件中。

例如,我们在这两种情况下都复制了 Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.dll,但没有复制 Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.dll。

作为一种解决方法,我使用“BeforeBuild”步骤复制了文件。

现在似乎可以构建。


B
Bronek

我没有遇到同样的问题,但类似。我有 WPF 主项目和引用的项目,其中引用的项目没有复制。我发现在我的例子中,主项目是为 NET 4.0 客户端配置文件设置的,并且为 NET 3.5 引用。当我将主项目设置为 3.5 时,引用项目的已编译 dll 开始复制。 (我不知道为什么,因为我通过实践解决了它)


u
user4869201

我也遇到了类似的问题,引用的 dll 没有复制到已发布文件夹的 bin 中。我使用的是 TFS 签出副本,该副本未将 bin 文件夹包含到应用程序中。 -> 所以只包含 bin 文件夹。 -> 构建引用的应用程序 -> 发布网站项目现在我在发布的文件夹中看到 bin 中所有引用的 dll


c
chviLadislav

我对 VS 2012 Express 也有类似的问题。我在我的项目中使用了 Tesseract 库。一切都很顺利,直到我在一个不止一个项目的解决方案中使用了这个项目。问题是一些通常放在文件夹 bin/debug/x86 或 bin/debug/x64 中的 DLL(liblept168.dll、libtesseract302.dll)仅在我重建整个解决方案时才被复制。更改一行并再次构建它会导致 DLL 被删除而不是复制回来。

我通过向启动项目添加创建缺失 DLL 的项目引用解决了这个问题。


J
John H

rzen 和其他人,谢谢 - 您的评论为我们带来了解决方案。

我们有一个针对 Microsoft.ReportViewer.Common.dll 和 Microsoft.ReportViewer.WebForms.dll 程序集(我们在“src”级别创建的单独“libs”文件夹)版本 10 的项目。但是当我们进行构建时,输出包括最近安装在构建服务器上的版本 12。

在这里使用注释,我们确保“复制本地”设置为 True,并且在项目文件中设置了标志。但是,它仍在部署版本 12。因此,我们发现的诀窍是确保在两个引用上也设置了“特定版本”属性。瞧,现在正在部署每个文件的第 10 版!

人们欢欣鼓舞。

JH


L
Lukos

如果您的项目不直接加载库,则不会始终部署它,即使它被显式引用!我很困惑,因为我可以在本地 Bin 目录中看到它,但在部署时却看不到。 Bin 目录中的 dll 是一个旧文件,在清理过程中没有被删除,这就是我感到困惑的原因。

完全清理和重建,它也不在我的本地 Bin 文件夹中,这向我显示了问题(我只在 web.config 中使用它)。然后我在项目中引用了 dll 文件本身并将其设置为复制到输出以确保它被部署。


P
Peter Mortensen

我不确定它是如何在 Visual Studio 2008 中设置的,但我几乎可以肯定您可能一直在使用 Post-Build 事件命令行。在那里,您可以告诉复制部署所需的 DLL 文件。下面给出一个例子:

mkdir $(SolutionDir)\Deployment
copy "$(SolutionDir)Your_Library_Name\Your_Dll_ForDeployement.dll" 
$(SolutionDir)\Deployment\

我检查了这个,但事实并非如此,无论如何谢谢你。
P
Peter Mortensen

我们可以使用 <Private>False</Private> 来不将引用的 DLL 文件复制到 bin 目录。当我们在单独的 TFS 构建服务器中构建应用程序时,这很有用,我们需要在其中构建应用程序,而不是将 DLL 文件复制到 bin 目录。


P
Peter Mortensen

检查引用了 DLL 文件的项目的框架。框架应该是 .NET 4.0。如果框架是客户端配置文件,请更正它。


G
Giles Roberts

添加参数

/deployonbuild=假

到 msbuild 命令行解决了这个问题。


C
Christian

在将旧网站升级到 WebApplications 时遇到了类似的问题。 “清理解决方案”命令将清除我故意留在 bin 文件夹中的所有外部 DLL 文件。

此外,不可能通过简单地引用它们来自动恢复这些 DLL,因为它们中的许多具有相同的文件名(当您使用许多特定于语言的资源时会发生这种情况)

像 stevie_c 一样,我利用了 Pre-Build 命令,但让它变得更简单:

我只是在 WebApplication 项目属性的 Pre-Build 操作中使用了 xcopy 命令。这样我就可以在构建开始之前带来必要的外部 DLL 文件。