ChatGPT解决这个技术问题 Extra ChatGPT

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

我的项目文件夹的 \lib 文件夹中有一些 dll 文件。在 dll 的属性页中,我选择了“构建操作”作为“内容”,将“复制到输出目录”选择为“始终复制”。

构建后,我实际上是在复制 dll,但它们在 \bin\Release\lib 中,而不是在 \bin\Release 中。

有没有办法将 dll 文件复制到 \bin\Release(而不是 \bin\Release\lib)而不编写构建后脚本或诉诸 nant 等?


P
Pharap

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

<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> 条目将确保它仍显示在 Visual Studio 的 UI 中。


我没有看到 ContentWithTargetPath 作为 VS 2015 中的构建操作选项。有没有办法添加它?
一旦我在 .csproj 文件中手动添加了该条目,它就会在 IDE 中显示为一个选项。但是我仍然无法从 IDE 编辑目标路径。
我唯一担心的是,未来版本的 MSBuild/.NET/Visual Studio/Whatever 将不支持此功能,因为 VS2015 UI 不显示此选项或 TargetPath 属性。
这对我有用。其他答案都不适合我。这应该是答案。
请注意,使用 ContentWithTargetPath 会中断增量编译(在 VS 2017 15.9.9 上测试)
A
Ani

将它们保留在 $(ProjectDir)\Lib 中,但将这些文件“As a link”添加到 .csproj 的根目录中。现在它们将被复制到 bin\Debug (或任何其他输出文件夹)而不在 lib 中。

编辑:当 ContentWithTargetPath 在我使用的 VS/MSBuild 版本中不可用时,这个答案被写回了。为可能不得不使用旧版本 VS 的人留下这个答案。请停止对此发表评论,我们都知道现在有更好的方法。


谢谢 ananthonline。我尝试了您的步骤,但没有帮助。可能是我做错了什么。这就是我正在做的事情,如果您认为不正确,请更正: 1. 从项目中排除这些 dll,但让它们位于 lib 中 2. 右键单击项目并“添加现有项目”。从 lib 中选择 dll 并将它们添加为“作为链接” 3. 右键单击 dll 并再次在“复制到输出目录”中选择“始终复制”。 4. 清理和重建。结果:我再次在 \bin\release\lib 中获得了那些 dll
请在配置后发布您的解决方案文件夹的屏幕截图
如果我尝试添加指向项目树中已有文件的链接,它会拒绝,而是再次将文件包含到项目中......
就像@Nyerguds 一样,我遇到的问题是您无法将链接添加到项目树中已经存在的文件中,因此这个答案并不能解决问题。
它不会淹没解决方案资源管理器中项目目录的根目录吗?对于许多这样的文件,这可能是一个问题。通常项目目录的根目录已经包含太多的各种文件。
s
sonny

如果您的主要目的是在不弄乱项目根目录的情况下包含 DLL,另一种解决方案是将 DLL 移动到单独的共享项目中,并将其添加为原始项目中的引用。

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

脚步

右键单击您的解决方案 -> 添加 -> 新项目 -> 共享项目

将 DLL 添加到此项目(在此项目的根目录中,而不是在“lib”子文件夹中)

(检查 DLL 文件属性设置是否正确,例如构建操作:内容和复制到输出目录:始终复制)

右键单击原始项目的引用 -> 添加引用 -> 共享项目

选择您之前创建的共享项目

设置如下所示:

https://i.stack.imgur.com/0ot1W.png


到目前为止,保持项目整洁的简单而优雅的解决方案。
我无法让它与 UAP 和 *.bin 文件一起使用。
e
erik_nw

添加 dll 文件作为对项目的引用,并在引用上将“复制本地”设置为 true。


谢谢埃里克。除了我无法添加作为参考的一个 dll 之外,这非常有效。添加为引用时出现的错误是无法添加对“libeay32.dll”的引用。请确保该文件是可访问的,并且它是一个有效的程序集或 COM 组件。
@MAnthony:只能将 .NET 程序集或 COM 互操作程序集添加为项目引用;本机 DLL 不能。您需要找到其他方法将 DLL 复制到 \bin\Release。
感谢 Erik、Michael 和 ananthonline。抱歉,由于我没有所需的声誉积分,因此无法支持您的答案和评论。
对于非托管 DLL,您将需要使用我在下面建议的方法。
d
dev-siberia

如果需要将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>

t
trojanfoe

要将我的帽子添加到此处,如果您想要包含整个目录的内容并且您不想在 Visual Studio 中跟踪每个单独的文件,那么您可以将其添加到您的项目文件中(对我来说这是一个 { 1} UWP C++ 项目的文件):

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

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


D
DefenestrationDay

在 VisualStudio 2015 中,如果您“使用链接添加”的 dll 位于同一项目的子文件夹中 - 它们将自动放置在文件夹中,并且输出也放置在您看到的文件夹中。

如果 dll 在磁盘上的另一个项目或目录中,而不是在项目的子文件夹中,您可以“使用链接添加”,它们将被放在根目录中就好了。


在 VS2012 中也一样。它拒绝让它们成为链接,只是将它们添加为内容。最后,可悲的是,最简单的解决方案似乎是将它们转储到项目根目录中。
A
AlainD

Visual Studio 2019 Professional v16.8.2 中,上述解决方案对我来说并不可靠。有时文件会复制,有时不会。经过多次尝试,感觉在 VS 的最新更新中可能出现了问题。

这个答案显示了如何使用构建后脚本...... OP 要求不要做的事情!因此,此答案仅适用于那些(像我一样)无法使用更传统方法的人。

右键单击项目并选择添加 > 现有项...

导航到 lib 文件夹并选择要添加的项目

在添加右侧,单击向下箭头并选择添加为链接

右键单击项目中新“lib”文件夹中的每个文件,并将“复制到输出目录”设置为“不复制”

打开项目属性 Build Events 并添加以下 Post-build 事件

,

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)

请注意,您可以在构建后事件中使用通配符来复制多个文件。


这是我在我从事的项目中看到的最常见的方法。此外,您可以将 xcopy 与 /d /y 标志一起使用,因此它只会复制较新的文件。 xcopy 还有一些可能对构建事件有用的选项。
K
Kyle

关于您的问题,以下步骤在 Visual Studio 2019 中对我有用:

在 Visual Studio 编辑器中,对于您的 dll,将“构建操作”设置设置为“内容”(这可能是可选的),将“复制到输出目录”设置为“不复制”。

然后将在项目 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”选项手动设置为“Always”或“PreserveNewest”。

在 Visual Studio 编辑器中,它仍然会显示文件“复制到输出目录”设置为“不复制”,但文件将在重建时复制到根输出目录。

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


C
ChuckEng

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

注意:我是在 VS2019 中做的,而且事情可能会因版本而异。

要让它工作,现在右键单击您的项目,然后选择“卸载项目”。然后右键单击卸载的项目并选择“编辑 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)。您可以使用一个技巧来使用 GetDirectoryNameOfFileAbove 将其定义到 .sln 文件所在的文件夹。 (留给读者作为练习)。此外,看起来他们在 2019 年无论如何都在命令行上正确处理了这个问题。是的 :) $(SolutionDir) 包含一个尾部反斜杠,因此后面没有。每个结果都必须有一个尾随反斜杠。

现在,如果您拥有 Pro 或更高版本,请不要在每次需要创建项目时都这样做。那会很蹩脚。相反,一旦您按照自己喜欢的方式设置项目,请选择 Project -> Export Template。你给它一个名字,下次你想创建一个像那个一样的项目时,只需在“新建项目”对话框中选择该名称。 (在旧版本中,我认为这是 Files -> Export Teamplate...。)


P
Petr Hendl

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

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

常见的 .dll 文件可以放在子文件夹中(如上面提到的“\lib”)并在属性中选择:

构建操作 =“帮助文件”

复制到 OutputDirectory = "如果更新"

这完全符合我的要求 - 在构建期间,.DLL 被复制到没有“\lib”子文件夹的输出目录中。


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅