【问题标题】:Referenced DLL not being copied to referencing project引用的 DLL 未复制到引用项目
【发布时间】:2020-03-18 00:34:20
【问题描述】:

这个问题可能已经被问过很多次了,也许我只是不擅长使用这里的搜索功能以及谷歌,但我还没有找到这个问题的答案。

我目前有两个项目,项目 X、项目 Y 和项目 Z(仅保存映射)

Project X 是一个 FluentNhibernate 项目,其中包含我的 sessionfactories 和类似的东西。所以这也是加载映射和事情的地方(这很重要,我怀疑这可能是我遇到问题的全部原因)

现在在 Project X 中,我引用了一个使用 Microsoft.SqlServer.Types.dll 的程序集。

项目 Y 是一项使用项目 X 进行数据库连接的服务。

所有 probjects 构建都可以在我的开发机器上找到并完美运行,但是当部署到我们的服务器时它们无法运行(运行时错误)。该错误非常模糊,因为它指出了一个缺失的 FluentNHibernate 程序集,而事实并非如此。

Procmon.exe 幸运地显示了尝试加载 Microsoft.SqlServer.Types.dll 的代码,因为服务器没有安装 SQL Server(我的客户端也没有安装,但它有一个管理工作室,很可能安装了这个。 DLL)。

到目前为止一切顺利,复制了 DLL 并且它工作正常(耶!)。

现在我想我会将程序集添加到项目 X 以确保将此引用复制到使用项目 X 的​​其他项目。这没有发生....所以我尝试设置“复制本地”设置为真。

遗憾的是,这仍然没有将 .dll 复制到引用项目 Y。

有没有办法实现这一点,或者这个 Visual Studio 很聪明并且意识到项目 Y 不需要这个 .dll 并因此拒绝复制它?

(由于项目 Z 需要实际引用并且项目 X 在运行时加载此程序集,因此 Z 和 X 之间没有“硬”引用)​​

任何 Stackoverflow 天才能否对此有所了解,因为老实说,我想知道它为什么会这样(理想情况下是让它表现得像我想要的那样)。

【问题讨论】:

    标签: .net visual-studio-2010 reference fluent-nhibernate .net-assembly


    【解决方案1】:

    这个问题已经得到解答,但我想我将包含一个通用的故障安全方法,用于将所有间接引用复制到项目的输出目录中。

    1. 对于您希望包含在输出中的所有引用,将 Copy Local 设置为 true
    2. 将复制的间接依赖代码(见下文)保存到名为CopyIndirectDependencies.targets 的文件中,并将目标文件放在您的项目目录中。
    3. 编辑您的.csproj.vbproj 以包含对您添加的.targets 文件的导入。请参见下面的示例。
    4. 构建您的项目,您应该将辅助依赖项自动复制到构建输出中。

    CopyIndi​​rectDependencies.targets 文件内容

    <?xml version="1.0" encoding="utf-8"?>
    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <PropertyGroup>
        <CopyIndirectDependencies   
          Condition="'$(CopyIndirectDependencies)'==''">true</CopyIndirectDependencies>
        <CopyIndirectDependenciesPdb
          Condition="'$(CopyIndirectDependenciesPdb)'==''">false</CopyIndirectDependenciesPdb>
        <CopyIndirectDependenciesXml
          Condition="'$(CopyIndirectDependenciesXml)'==''">false</CopyIndirectDependenciesXml>
      </PropertyGroup>
    
    
      <!-- BuildXxx part -->
    
      <Target Name="CopyIndirectDependencies"
              Condition="'$(CopyIndirectDependencies)'=='true'"
              DependsOnTargets="DetectIndirectDependencies">
        <Copy Condition="'%(IndirectDependency.FullPath)'!=''"
              SourceFiles="%(IndirectDependency.FullPath)"
              DestinationFolder="$(OutputPath)"
              SkipUnchangedFiles="true" >
          <Output TaskParameter="CopiedFiles"
                  ItemName="IndirectDependencyCopied" />
        </Copy>
        <Message Importance="low"
                 Condition="'%(IndirectDependencyCopied.FullPath)'!=''
                   and '%(IndirectDependencyCopied.Extension)'!='.pdb'
                   and '%(IndirectDependencyCopied.Extension)'!='.xml'"
                 Text="Indirect dependency copied: %(IndirectDependencyCopied.FullPath)" />
      </Target>
    
      <Target Name="DetectIndirectDependencies"
              DependsOnTargets="ResolveAssemblyReferences">
    
        <Message Importance="low"
                 Text="Direct dependency: %(ReferencePath.Filename)%(ReferencePath.Extension)" />
        <Message Importance="low"
                 Text="Indirect dependency: %(ReferenceDependencyPaths.Filename)%(ReferenceDependencyPaths.Extension)" />
    
        <!-- Creating indirect dependency list -->
        <CreateItem Include="%(ReferenceDependencyPaths.FullPath)"
                    Condition="'%(ReferenceDependencyPaths.CopyLocal)'=='true'">
          <Output TaskParameter="Include"
                  ItemName="_IndirectDependency"/>
        </CreateItem>
        <CreateItem Include="%(ReferenceDependencyPaths.RootDir)%(ReferenceDependencyPaths.Directory)%(ReferenceDependencyPaths.Filename).xml"
                    Condition="'%(ReferenceDependencyPaths.CopyLocal)'=='true' and '$(CopyIndirectDependenciesXml)'=='true'">
          <Output TaskParameter="Include"
                  ItemName="_IndirectDependency"/>
        </CreateItem>
        <CreateItem Include="%(ReferenceDependencyPaths.RootDir)%(ReferenceDependencyPaths.Directory)%(ReferenceDependencyPaths.Filename).pdb"
                    Condition="'%(ReferenceDependencyPaths.CopyLocal)'=='true' and '$(CopyIndirectDependenciesPdb)'=='true'">
          <Output TaskParameter="Include"
                  ItemName="_IndirectDependency"/>
        </CreateItem>
    
        <!-- Filtering indirect dependency list by existence -->
        <CreateItem Include="%(_IndirectDependency.FullPath)"
                    Condition="Exists('%(_IndirectDependency.FullPath)')">
          <Output TaskParameter="Include"
                  ItemName="IndirectDependency"/>
        </CreateItem>
    
        <!-- Creating copied indirect dependency list -->
        <CreateItem Include="@(_IndirectDependency->'$(OutputPath)%(Filename)%(Extension)')">
          <Output TaskParameter="Include"
                  ItemName="_ExistingIndirectDependency"/>
        </CreateItem>
    
        <!-- Filtering copied indirect dependency list by existence -->
        <CreateItem Include="%(_ExistingIndirectDependency.FullPath)"
                    Condition="Exists('%(_ExistingIndirectDependency.FullPath)')">
          <Output TaskParameter="Include"
                  ItemName="ExistingIndirectDependency"/>
        </CreateItem>
    
      </Target>
    
    
      <!-- Build sequence modification -->
    
      <PropertyGroup>
        <CoreBuildDependsOn>
          $(CoreBuildDependsOn);
          CopyIndirectDependencies
        </CoreBuildDependsOn>
      </PropertyGroup>
    </Project>
    

    导入示例项目

    <?xml version="1.0" encoding="utf-8"?>
    <Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    
      ...
    
      <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
      <Import Project="CopyIndirectDependencies.targets" /> <!-- ADD THIS LINE!! -->
    
      ...
    
    </Project>
    

    来源:http://blog.alexyakunin.com/2009/09/making-msbuild-visual-studio-to.html

    【讨论】:

    • 在项目文件中添加步骤 3 中的行是否重要?例如,它必须在 AfterBuild 目标下还是其他地方(或任何地方)?
    • 嗯,这在 Visual Studio 2012 中不起作用。我希望我错了。
    • @longda:请参阅我获取此答案的文章。它有一个示例项目。
    • 我通过将 CoreBuildDependsOn 更改为 ResolveReferencesDependsOn,使 Visual Studio 2012 无需手动更改构建目标即可工作。可能有更好的等价物
    【解决方案2】:

    现在我想我会将程序集添加到项目 X 以确保将此引用复制到使用项目 X 的​​其他项目。这没有发生....所以我尝试设置“复制Local' 设置为 true。

    你还在谈论 Microsoft.SqlServer.Types.dll 对吧?

    前段时间我也遇到过同样的问题,实际上 sqlserver 类型不应该在您的安装中复制和重新分发。 “安装”它的正确方法是下载 sql server 运行时(它包含在 sql server 管理工具中,这就是它在本地工作的原因)。

    因为是前段时间,我不能 100% 确定以下信息是否正确以及是否有效,但只需尝试仅安装 Microsoft® System CLR Types for Microsoft® SQL Server® 2012。在此下载页面上展开安装说明并向下滚动到 CLR 类型下载...

    使用this link for SQL Server 2008

    在目标服务器上安装它。这只会安装运行这种类型的 dll 所需的东西...

    【讨论】:

    • 我还在谈论 Microsoft.SqlServer.Types.dll 是的。但是在这种情况下,为什么将它与您的实际软件一起分发是不好的呢?这里有一些最佳实践吗?
    • 类型 dll 只是 dll 的包装器,SQL Server 本身也使用这些 dll 来执行空间操作......这些 dll 是用 C/C++ 编写的,如果你只是复制,则不会被复制在类型 dll 上...您可能还会复制 SQLServerSpatial.dll (这是本机 dll)
    • 好吧,我在源代码中使用了这些类型,这些类型由第三方编写,我已将其更改为使用具有地理信息和 sql server 2012 方言的流利的 nhibernate。但是,根据您提供的信息安装 CLR 类型似乎可行。所以我会再做一些测试,如果这些测试成功,我会标记你的答案。也就是说,我怀疑 Visual Studio 拒绝复制 DLL,因为它们是用 C/C++ 编写的。根本问题仍然存在,我希望在这里得到答案,但是由于 Microsoft.SqlServer.Types.dll 而在此处找到方法的其他人应该使用安装程序。
    • tbh 我对复制 dll 并没有真正理解您的问题,也许最好的办法是在 SO 上提出一个新问题,并提供一些明确的解释;)无论如何,您可以设置所有项目的输出 bin 文件夹到一个公共位置,例如..\Bin 而不是 Debug\Bin... 这会将所有 dll 复制到一个地方。对于分发东西,如果您有 3rd 方程序集和依赖项,我认为最好是构建一个安装项目,否则您可能会错过其他依赖项。您还可以通过将两种 sql 类型的 dll 添加到我猜想的设置中来手动分发这两种类型的 dll(从未尝试过)
    【解决方案3】:

    【讨论】:

    • 该链接现已失效。这就是最好至少从链接中复制解决方案而不仅仅是发布链接本身的原因。
    猜你喜欢
    • 2014-06-26
    • 2018-11-02
    • 2014-10-25
    • 1970-01-01
    • 1970-01-01
    • 2016-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多