I have a few dll files in \\lib folder of my project folder. In the property page of dll, I have selected \"Build Action\" as \"Content\" and \"Copy to Output Directory\" as
It seems in VisualStudio 2015 that if the dlls you are 'adding with a link' are in a subfolder of that same project - they will be automatically put a folder, and the output is also placed in a folder like you saw.
If the dlls are in another project or directory on disk not in a subfolder of the project, you can 'Add with a link', and they will be put in the root directory just fine.
An alternate method is just to leave the items as type None
. In the solution explorer, click on the ones you want to deploy and set the Content
property to True
.
Note: I did this in VS2019, and things can change from version to version.
To get this to work, now right-click on your project, and select "Unload Project". Then right-click on the unloaded project and select "Edit project_name.vcxproj".
In the editor, go all the way to the bottom of the file and insert this target right right before the trailing </Project>
tag:
<Target Name="CopyContent" AfterTargets="Build">
<Copy SourceFiles="@(None)" Condition="'%(None.DeploymentContent)' == 'true'" DestinationFolder="$(OutputPath)" ContinueOnError="true" />
</Target>
Now right click on the unloaded project and select "Reload Project". Select to save and close if you are prompted.
I also set the OutputDirectory
to:
$(SolutionDir)bin\$(Configuration)\$(Platform)\
and the IntermediateDirectory
to:
$(SolutionDir)obj\$(Configuration)\$(ProjectName)\$(Platform)\
in the Project Properties General page. This puts the output in a "bin" folder, and the intermediates in an "obj" folder in the root of your solution.
Note: The $(SolutionDir)
is not defined when you run MSBuild from the command line. There is a trick you can use to define that to the folder where the .sln file lives using GetDirectoryNameOfFileAbove. (left as an exercise for the reader). Also, it looks like in 2019 they are handling this correctly on the command line anyway. Yeah :) The $(SolutionDir)
contains a trailing backslash, hence none after it. The results of each must have a trailing backslash.
Now, if you own Pro or above, please don't do this every time you need to create a project. That would be lame. Instead, once you have your project setup just the way you like it, select Project -> Export Template
. You give it a name, and the next time you want to create a project just like that one, just choose that name in the New Project dialog. (In older version, I think this was Files -> Export Teamplate...
.)
Keep them in $(ProjectDir)\Lib
, but add those files "As a link" to the root of your .csproj. Now they will get copied to bin\Debug (or whatever other output folder) without being in lib.
EDIT: This answer was written way back when ContentWithTargetPath was not available in the versions of VS/MSBuild I was using. Leaving this answer here for people who might have to use an older version of VS. Please stop commenting on this, we all know there are better ways now.
Add the dll-files as a reference to the project, and on the reference set "Copy local" to true.
If you need to copy files from the Libs directory to the root folder 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>
To any other folder, including Libs(RecursiveDir) folder
<ItemGroup Condition="'$(Platform)' == 'x86'">
<None Include="Libs\x86\**" Link="mycustomfolder\%(RecursiveDir)%(Filename)%(Extension)" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
instead of <Content>
use <ContentWithTargetPath>
and specify target path, like this:
<ItemGroup>
<ContentWithTargetPath Include="lib\some_file.dat">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>some_file.dat</TargetPath>
</ContentWithTargetPath>
</ItemGroup>
Note that this entry may not be visible from Visual Studio (2012, 2015, 2017), but once manually added to the csproj, it will appear in Visual Studio. The target path will not be editable through the UI though.