如何让 Visual Studio 将 DLL 文件复制到输出目录?

Posted

技术标签:

【中文标题】如何让 Visual Studio 将 DLL 文件复制到输出目录?【英文标题】:How to make Visual Studio copy a DLL file to the output directory? 【发布时间】:2010-12-19 01:31:54 【问题描述】:

我有一个依赖于外部 DLL 文件的 Visual Studio C++ 项目。构建项目时,如何让 Visual Studio 自动将此 DLL 文件复制到输出目录(调试/发布)?

【问题讨论】:

【参考方案1】:

我也有类似的问题。在我的项目中,有几个外部 DLL。所以我在项目中创建了一个名为“lib”的新文件夹,并将所有外部dll复制到这个文件夹中。

    添加对这些 DLL 的引用。 转到项目引用>dll 属性并更改以下属性 enter image description here

【讨论】:

【参考方案2】:

project.csproj 文件中添加内置 COPY:

  <Project>
    ...
    <Target Name="AfterBuild">
      <Copy SourceFiles="$(ProjectDir)..\..\Lib\*.dll" DestinationFolder="$(OutDir)Debug\bin" SkipUnchangedFiles="false" />
      <Copy SourceFiles="$(ProjectDir)..\..\Lib\*.dll" DestinationFolder="$(OutDir)Release\bin" SkipUnchangedFiles="false" />
    </Target>
  </Project>

【讨论】:

VS存在长期bug,请使用ProjectDir而不是SolutionDir【参考方案3】:
xcopy /y /d  "$(ProjectDir)External\*.dll" "$(TargetDir)"

您也可以参考相对路径,下一个示例将在项目文件夹上一层的文件夹中找到 DLL。如果您有多个项目在单个解决方案中使用 DLL,则这会将 DLL 的源代码放置在一个公共区域中,当您将其中任何一个设置为启动项目时都可以访问。

xcopy /y /d  "$(ProjectDir)..\External\*.dll" "$(TargetDir)"

/y 选项无需确认即可复制。 /d 选项检查文件是否存在于目标中,是否仅在源的时间戳比目标的时间戳更新时才复制。

我发现至少在较新版本的 Visual Studio 中,例如 VS2109,$(ProjDir) 是未定义的,必须改用 $(ProjectDir)

xcopy 中省略目标文件夹应默认为输出目录。理解$(OutDir) 本身没有帮助的原因很重要。

$(OutDir),至少在最新版本的 Visual Studio 中,被定义为输出文件夹的相对路径,例如 bin/x86/Debug。单独使用它作为目标将从项目输出文件夹开始创建一组新文件夹。例如:… bin/x86/Debug/bin/x86/Debug

将它与项目文件夹结合起来应该可以将您带到正确的位置。例如:$(ProjectDir)$(OutDir)

不过$(TargetDir)会一步一步提供输出目录。

Microsoft's list of MSBuild macros for current and previous versions of Visual Studio

【讨论】:

【参考方案4】:

$(OutDir) 在 VS2013 中原来是相对路径,所以我不得不将它与 $(ProjectDir) 结合起来才能达到预期的效果:

xcopy /y /d  "$(ProjectDir)External\*.dll" "$(ProjectDir)$(OutDir)"

顺便说一句,您可以通过在开头添加“echo”来轻松调试脚本,并在构建输出窗口中观察展开的文本。

【讨论】:

$(TargetDir) 可以替换 $(ProjectDir)$(OutDir) 因为它是两者的组合。 在我没有 /d 的情况下,它会引发访问被拒绝错误。但是根据文档的 /d 是针对日期的。不确定是什么联系。 如果源文件较旧或与现有文件相同,添加 /d 可防止覆盖。如果目标被另一个进程锁定,可能会出现拒绝访问错误。 我建议添加/f 参数,如xcopy /y /f 以获得有关源目录和目标目录的详细输出。文档:docs.microsoft.com/en-us/windows-server/administration/…【参考方案5】:

当我尝试将输出 dll 从一个 C++ 项目复制到同一解决方案中另一个 C# 项目的发布和调试文件夹时,上面 cmets 部分中的详细信息对我不起作用(VS 2013)。

我必须添加以下构建后操作(右键单击具有 .dll 输出的项目)然后 属性 -> 配置属性 -> 构建事件 -> 构建后事件 -> 命令行

现在我添加了这两行以将输出 dll 复制到两个文件夹中:

xcopy /y $(TargetPath) $(SolutionDir)aeiscontroller\bin\Release
xcopy /y $(TargetPath) $(SolutionDir)aeiscontroller\bin\Debug

【讨论】:

【参考方案6】:

(此答案仅适用于 C# 而不是 C++,抱歉我误读了原始问题)

我以前经历过这样的 DLL 地狱。我的最终解决方案是将托管 DLL 中的非托管 DLL 作为二进制资源存储,并在程序启动时将它们解压缩到临时文件夹中,并在释放时将其删除。

这个应该是 .NET 或 pinvoke 基础架构的一部分,因为它非常有用....它使您的托管 DLL 易于管理,无论是使用 Xcopy 还是作为项目中的引用更大的 Visual Studio 解决方案。完成此操作后,您不必担心构建后事件。

更新:

我在另一个答案https://***.com/a/11038376/364818 中发布了代码

【讨论】:

我同意,它应该是框架的一部分(静态链接 dll 等)——值得注意的是,将 dll 存储为资源然后在运行时提取它可能会导致某些问题公司环境(特别是如果他们有相当主动的防病毒软件)。 同意 BrainSlug83。我们有 McAfee,它是为恶意软件/垃圾付费的,它只是阻止 dll 在临时目录中执行、移动、更改。【参考方案7】:

在您的项目中使用构建后操作,并添加命令以复制有问题的 DLL。构建后操作以批处理脚本的形式编写。

输出目录可以引用为$(OutDir)。项目目录为$(ProjDir)。尝试在适用的情况下使用相对路径,以便您可以复制或移动项目文件夹而不会破坏构建后操作。

【讨论】:

另外值得指出的是,他可以通过 Project > Properties > Build Events > Post-Build Event 设置构建后事件。 示例:eyeung003.blogspot.com/2009/11/… 如果链接中断:"xcopy /y "$(ProjectDir)*.dll" "$(OutDir)" 将 /d 标志添加到 xCopy 以防止不必要地重新复制输出目录中未更改的文件。 $(TargetDir) 而不是$(OutDir)

以上是关于如何让 Visual Studio 将 DLL 文件复制到输出目录?的主要内容,如果未能解决你的问题,请参考以下文章

如何让 DLL 项目更新 Visual Studio 中 C++ 项目中的每个构建

让 dll 包含在 Visual Studio 中工作

如何在 Visual Studio 2010 中正确引用 dll?

在 Visual Studio 2012 中,如何将资源文件 (.rc) 与 c ++ dll 链接

visual studio 2008如何引用dll

如何在 Visual Studio 中设置 DLL 文件的路径?