Search code examples
c#directorymsbuildcopycsproj

How to tell Visual Studio (MSBuild) to copy all files in the folder, including empty folders?


I have a Template folder in the project that should not be compiled or anything but should be included when built so my app can copy it later. The content may include C# files as well. I previously use this declaration to copy everything:

    <ItemGroup>
        <Compile Remove="Template\**\**" />
        <Content Remove="Template\**\**" />
        <Folder Remove="Template\**\**" />
        <None Include="Template\**\**">
            <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </None>
    </ItemGroup>

However today I realize it doesn't include empty folders. I would like to use a wildcard declaration instead of separate <Folder Include="..." /> like other articles on SO as the content of Template may be changed later and I do not want me or my teammate forget to add it. Is there such declaration?


Solution

  • There isn't a flag or declaration or metadata for the CopyToOutputDirectory feature that will make it copy empty directories.

    The CopyToOutputDirectory feature uses the Copy task and the Copy task doesn't copy empty directories.

    There is discussion/feature requests about MSBuild copying empty directories so this may change in the future but it is not available today.

    In the general case the question should be asked, does the copied directory structure really need to have empty directories? Can it be acceptable (or made to be acceptable) that an empty directory is not included in the output? For example if the directory structure is consumed by code, can the consuming code be updated to gracefully handle 'missing' directories?

    For when empty directories are required, two approaches are:

    • Create a custom MSBuild target that statically builds the expected directory structure in the output directory. This target would be straight-forward to implement, it could be a single MakeDir task, but would require maintenance (i.e. changes) whenever the directory structure changes. If changes are infrequent, this may be fine.
    • Create a custom MSBuild target that dynamically walks the directory structure and creates matching directories in the output directory. This target would require more effort to implement but won't go 'out of date' when the directory structure is changed.

    If these tasks are non-destructive and only add missing directories, they could be run either before or after the CopyToOutputDirectory step happens in the build.

    If one of these targets is implemented, it would be a good idea to also implement a target that is invoked on a clean that removes the directory structure.