VisualStudio 中: 如何在不复制文件夹结构的情况下“复制到输出目录”?

我项目文件夹中的\lib文件夹里有一些dll文件。在dll的属性页面中,我已经将 "Build Action" 设置为 "Content",并将 "Copy to Output Directory" 设置为 "Copy always"。

在构建完成后,我实际上确实得到了dll文件的复制,但它们位于 \bin\Release\lib 文件夹中,而不是 \bin\Release 文件夹中。

有没有办法在不编写post-build 脚本或使用 nant 等工具的情况下将 dll 文件复制到 \bin\Release 文件夹中(而不是 \bin\Release\lib)?

125130 次浏览

将它们保存在 $(ProjectDir)\Lib中,但是将这些文件“ 作为纽带”添加到您的。Csproj.现在它们将被复制到 bin Debug (或任何其他输出文件夹) ,而不在 lib 中。

编辑: 这个答案是在我使用的 VS/MSBuild 版本中 ContentWithTargetPath 不可用的时候写的。把这个答案留给那些可能不得不使用旧版 VS 的人,请不要再评论这个问题了,我们都知道现在有更好的方法。

添加 dll-files 作为对项目的引用,并在引用上将“ Copylocal”设置为 true。

我在 Visual Studio 2010/C # 项目中也遇到过同样的问题。

对于程序集(即具有。NET 接口)在解决方案资源管理器中使用项目下的文件夹“引用”。右键单击它,选择“添加现有项目”,然后找到您的。组装。

Dll 文件可以放在一个子文件夹中(正如上面提到的“ lib”) ,并在属性中选择:

  • Build Action = “ HelpFiles”
  • 复制到 OutputDirectory = “ If Newer”

这正如我所希望的那样工作——在构建期间,。将 DLL 复制到输出目录,但不包含“ lib”子文件夹。

在 VisualStudio 2015中,如果你用链接添加的 dls 是 在同一个项目的子文件夹中,它们会自动放入一个文件夹,输出也会像你看到的那样放入一个文件夹。

如果 dls 位于磁盘 不在项目的子文件夹中上的另一个项目或目录中,您可以“ Add with a link”,它们将被放在根目录中。

使用 <ContentWithTargetPath>代替 <Content>并指定目标路径,如下所示:

<ItemGroup>
<ContentWithTargetPath Include="lib\some_file.dat">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>some_file.dat</TargetPath>
</ContentWithTargetPath>
<None Include="lib\some_file.dat" />
</ItemGroup>

注意,这个条目可能在 Visual Studio (2012,2015,2017)中不可见,但是一旦手动添加到 csproj 中,它将出现在 Visual Studio 中。但是目标路径不能通过 UI 进行编辑。

为文件添加 <None>条目将确保它仍然显示在 VisualStudio 的 UI 中。

如果您的主要目的是在不弄乱项目根目录的情况下包含 DLL,那么另一个解决方案是将 将 DLL 移动到单独的共享项目作为参考添加到原始项目中。

(请注意,这篇文章并没有直接回答这个问题,因为它没有保留文件夹和项目结构,但我发现这种方法很有用,因为我能够在我的案例中重组我的项目,因为我想避免其他方法的一些缺点

步骤

  • 右键单击 Solution -> Add -> New Project -> Shared Project
  • 将 DLL 添加到该项目(在该项目的根目录中,而不是在“ lib”子文件夹中)
  • (检查 DLL 文件属性设置是否正确,例如 Build Action: ContentCopy to Output Directory: Copy Always)
  • 右键单击原始项目的 References -> Add Reference -> Shared Projects
  • 选择前面创建的共享项目

设置如下:

solution-explorer-screenshot

如果需要将文件从 Libs 目录复制到根文件夹 VS2017:

<ItemGroup Condition="'$(Platform)' == 'x64'">
<None Include="Libs\x64\**" Link="\%(Filename)%(Extension)" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup Condition="'$(Platform)' == 'x86'">
<None Include="Libs\x86\**" Link="\%(Filename)%(Extension)" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

到任何其他文件夹,包括 Libs (RecursiveDir)文件夹

<ItemGroup Condition="'$(Platform)' == 'x86'">
<None Include="Libs\x86\**" Link="mycustomfolder\%(RecursiveDir)%(Filename)%(Extension)" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

另一种方法是将项目保留为 None类型。在解决方案资源管理器中,单击要部署的资源管理器,并将 Content属性设置为 True

注意: 我是在 VS2019中这样做的,而且在不同版本之间可能会有所不同。

为了让这个工作,现在右键单击您的项目,并选择“卸载项目”。然后右键单击卸载的项目并选择“ Edit project _ name”。Vcxproj”。

在编辑器中,一直到文件的底部,然后在后面的 </Project>标记之前插入这个目标:

  <Target Name="CopyContent" AfterTargets="Build">
<Copy SourceFiles="@(None)" Condition="'%(None.DeploymentContent)' == 'true'" DestinationFolder="$(OutputPath)" ContinueOnError="true" />
</Target>

现在右键点击卸载的项目,选择“重新加载项目”。选择保存和关闭,如果你被提示。

我还将 OutputDirectory设置为:

$(SolutionDir)bin\$(Configuration)\$(Platform)\

以及 IntermediateDirectory:

$(SolutionDir)obj\$(Configuration)\$(ProjectName)\$(Platform)\

在“项目属性”常规页中。这将输出放在“ bin”文件夹中,中间层放在解决方案根目录中的“ obj”文件夹中。

注意: 从命令行运行 MSBuild 时没有定义 $(SolutionDir)。您可以使用一个技巧将其定义到。Sln 文件使用 GetDirectoryNameOfFileabove 生存。(留给读者作为练习)。而且,看起来2019年他们在命令行上正确地处理了这个问题。Yeah:) $(SolutionDir)包含一个反斜杠,因此后面没有反斜杠。每个结果都必须有一个反斜杠。

现在,如果你拥有专业或以上,请不要这样做,每次你需要创建一个项目。那就太逊了。相反,一旦您按照自己喜欢的方式设置了项目,请选择 Project -> Export Template。你给它一个名字,下次你想创建一个类似的项目时,只需要在新建项目对话框中选择这个名字。(在旧版本中,我认为这是 Files -> Export Teamplate...。)

如果你想要包含一个完整的内容目录,并且你不想在 Visual Studio 中追踪每个文件,那么你可以在你的项目文件中添加这个(对我来说,这是一个 UWP C + + 项目的 .vcxproj文件) :

<ItemGroup>
<Content Include="Content\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

请注意,Content目录 必须与项目文件在同一目录中是为了保留目录结构。

关于你的问题,以下步骤对我在 Visual Studio 2019中起作用:

在 Visual Studio 编辑器中,对于 dll,将“ Build Action”设置为“ Content”(这可能是可选的) ,将 “复制到输出目录”设置为 “不要复制”

然后将在项目 Csproj文件中生成以下内容:

<ItemGroup>
<Content Include="lib\IncludedDLL.dll" />
</ItemGroup>

将条目修改为以下内容:

<ItemGroup>
<Content Include="lib\IncludedDLL.dll" />
<Content Include="lib\IncludedDLL.dll">
<Link>IncludedDLL.dll</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>

可以将项目 Csproj文件 手动操作中的 “ CopyToOutputDirectory”选项设置为 “永远”“保持最新”

在 VisualStudio 编辑器中,它仍然会显示文件“复制到输出目录”设置为“不复制”是文件 将被复制的根输出目录 在重建的时候

如果您不想将文件复制到根输出目录,则不需要上述更改,因此如果是这种情况,您可以手动删除项目 csproj 文件中的上述更改,以恢复到非复制行为。

上述解决方案在 Visual Studio 2019 Professional v16.8.2中不能可靠地为我工作。有时文件会复制,有时不会。经过多次尝试之后,我感觉 VS 的最新更新可能出现了一些问题。

这个答案展示了如何使用构建后脚本... OP 要求 没有做的事情!因此,这个答案只是为那些(像我一样)无法得到更传统的方法工作。

  • 右键单击该项目并选择“添加 > 现有项...”。
  • 导航到 lib文件夹并选择要添加的项目
  • Add的右边,单击向下箭头并选择 Add As Link
  • 右键单击项目中新的“ lib”文件夹中的每个文件,并将“复制到输出目录”设置为“不复制”
  • 打开项目属性 Build Events并添加以下生成后事件

,

rem Copy 3rd party DLL(s) to the output directory on successful build
COPY $(ProjectDir)lib\Something.dll $(TargetDir)
COPY $(ProjectDir)lib\SomethingElse.dll $(TargetDir)

注意,可以在生成后事件中使用通配符复制多个文件。

我在 VS2022中使用了这个:

<ItemGroup>
<ContentWithTargetPath Include="LibFolder\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>%(Filename)%(Extension)</TargetPath>
</ContentWithTargetPath>
</ItemGroup>