我的项目文件夹的 \lib 文件夹中有一些 dll 文件。在 dll 的属性页中,我选择了“构建操作”作为“内容”,将“复制到输出目录”选择为“始终复制”。
构建后,我实际上是在复制 dll,但它们在 \bin\Release\lib 中,而不是在 \bin\Release 中。
有没有办法将 dll 文件复制到 \bin\Release(而不是 \bin\Release\lib)而不编写构建后脚本或诉诸 nant 等?
代替 <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 中。
将它们保留在 $(ProjectDir)\Lib
中,但将这些文件“As a link”添加到 .csproj 的根目录中。现在它们将被复制到 bin\Debug (或任何其他输出文件夹)而不在 lib 中。
编辑:当 ContentWithTargetPath 在我使用的 VS/MSBuild 版本中不可用时,这个答案被写回了。为可能不得不使用旧版本 VS 的人留下这个答案。请停止对此发表评论,我们都知道现在有更好的方法。
如果您的主要目的是在不弄乱项目根目录的情况下包含 DLL,另一种解决方案是将 DLL 移动到单独的共享项目中,并将其添加为原始项目中的引用。
(请注意,这篇文章没有直接回答这个问题,因为它不保留文件夹和项目结构,但我发现这种方法很有用,因为我能够在我的案例中重组我的项目,并且因为我想避免一些这里其他方法的缺点。)
脚步
右键单击您的解决方案 -> 添加 -> 新项目 -> 共享项目
将 DLL 添加到此项目(在此项目的根目录中,而不是在“lib”子文件夹中)
(检查 DLL 文件属性设置是否正确,例如构建操作:内容和复制到输出目录:始终复制)
右键单击原始项目的引用 -> 添加引用 -> 共享项目
选择您之前创建的共享项目
设置如下所示:
https://i.stack.imgur.com/0ot1W.png
添加 dll 文件作为对项目的引用,并在引用上将“复制本地”设置为 true。
如果需要将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>
要将我的帽子添加到此处,如果您想要包含整个目录的内容并且您不想在 Visual Studio 中跟踪每个单独的文件,那么您可以将其添加到您的项目文件中(对我来说这是一个 { 1} UWP C++ 项目的文件):
<ItemGroup>
<Content Include="Content\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
请注意,为了保留目录结构,Content
目录必须与项目文件位于同一目录中。
在 VisualStudio 2015 中,如果您“使用链接添加”的 dll 位于同一项目的子文件夹中 - 它们将自动放置在文件夹中,并且输出也放置在您看到的文件夹中。
如果 dll 在磁盘上的另一个项目或目录中,而不是在项目的子文件夹中,您可以“使用链接添加”,它们将被放在根目录中就好了。
在 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)
请注意,您可以在构建后事件中使用通配符来复制多个文件。
关于您的问题,以下步骤在 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 文件中的上述更改以恢复为非复制行为。
另一种方法是将项目保留为类型 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...
。)
我在 Visual Studio 2010 / C# 项目中遇到了同样的问题。
对于程序集(即具有 .NET 接口),请使用解决方案资源管理器中项目下的文件夹“References”。右键单击它,选择“添加现有项目”并找到您的 .dll 程序集。
常见的 .dll 文件可以放在子文件夹中(如上面提到的“\lib”)并在属性中选择:
构建操作 =“帮助文件”
复制到 OutputDirectory = "如果更新"
这完全符合我的要求 - 在构建期间,.DLL 被复制到没有“\lib”子文件夹的输出目录中。
ContentWithTargetPath
会中断增量编译(在 VS 2017 15.9.9 上测试)