When using the following does not return empty directories.
<ItemGroup>
<DirectorySet Include="$(ThisDir)\**"/>
</ItemGroup>
My question is why does a call like this not create a collection set off all objects Is there a way to have the collection return the empty directories as well
I am trying use collection sets that need to have all the specified files and directories included in them for proper processing whether it be an empty directory or not. The strange thing I noticed is if I do a call something like:
<DirectorySet Include="$(ThisDir)"/>
It will return that directory alone as a collection item.
Please help, I am on a deadline for a project and this is going to set me back quite a bit.
Thanks in advance!!!

Recursive does not get Empty Directories
Mindking
Here is a task that I wrote that will return either files or directories (empty or not) under a given path:
namespace Sedodream.MSBuild.Tasks
{
/// <summary>
/// This task will locate all the directories under a given path.
/// </summary>
public class FindUnder : Task
{
#region Fields
public ITaskItem path;
public ITaskItem [] directories;
public bool findFiles;
public bool findDirectories;
#endregion
public FindUnder()
{
this.findDirectories = false;
this.findFiles = false;
}
#region Properties
/// <summary>
/// This is the directory to search under for sub directories.
/// This directory will not be included in the <c>Directories</c> item.
/// </summary>
[Required]
public ITaskItem Path
{
get { return this.path; }
set { this.path = value; }
}
public bool FindFiles
{
get { return this.findFiles; }
set { this.findFiles = value; }
}
public bool FindDirectories
{
get { return this.findDirectories; }
set { this.findDirectories = value; }
}
/// <summary>
/// An <c>ITaskItem</c> containing all of the sub directories under <c>Path</c>.
/// </summary>
[Output]
public ITaskItem[] FoundItems
{
get { return this.directories; }
set { this.directories = value; }
}
#endregion
public override bool Execute()
{
string fullPath = this.Path.GetMetadata("Fullpath");
if (string.IsNullOrEmpty(fullPath) || !Directory.Exists(fullPath))
{
string message = string.Format("Path specified {0} doesn't exist", fullPath);
throw new Exception(message);
}
if (!findFiles && !findDirectories)
{
string message = "Either FindFiles or FindDirectories must be true";
throw new Exception(message);
}
DirectoryInfo dir = new DirectoryInfo(fullPath);
FileInfo [] files = new FileInfo[0];
DirectoryInfo [] subDirs = new DirectoryInfo[0];
if( findFiles)
{
files = dir.GetFiles("*",SearchOption.AllDirectories);
}
if( findDirectories )
{
subDirs = dir.GetDirectories("*",SearchOption.AllDirectories);
}
List<ITaskItem> items = new List<ITaskItem>();
foreach(FileInfo fInfo in files)
{
items.Add(new TaskItem(fInfo.FullName));
}
foreach(DirectoryInfo dInfo in subDirs)
{
items.Add(new TaskItem(dInfo.FullName));
}
this.directories = items.ToArray();
return true;
}
}
}
Here is a sample of its use:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Find">
<UsingTask AssemblyFile="C:\MSBuild\Tasks\Sedodream.MSBuild.Tasks.dll" TaskName="FindUnder"/>
<PropertyGroup>
<SearchPath>.</SearchPath>
</PropertyGroup>
<ItemGroup>
<Path Include="$(SearchPath)"/>
</ItemGroup>
<Target Name="Find">
<FindUnder Path="@(Path)" FindFiles="true" FindDirectories="true">
<Output ItemName="Items" TaskParameter="FoundItems"/>
</FindUnder>
<Message Text="Found items: @(Items,'%0d%0a')" Importance="high"/>
</Target>
</Project>
Sayed Ibrahim Hashimi
www.sedodream.com
Oscar Marquez
Hi Brian,
I gave the code you listed above a spin and indeed, when you use Include="$(ThisDir)" it does list the folder even though it is empty, and as soon as you start using wildcards, only files are listed (no folders at all are listed in the item, not even non-empty ones, just files).
There is a way around this, but it is a bit of a hack. Use the 'Exec' task to execute the following command:
dir c:\temp2 /s /b > c:\temp2.txt
- c:\temp2 is the root folder from where you want to start
- /s means recursive, /b means bae format (no headers)
- > is the xml notation for > to send the output of the dir command to a file
The reason I write this to a file is because at present there is no other way of getting the output of an Exec task back into msbuild.
Next, you use the ReadLinesFromFile task to read the contents of the file into an item like this:
<ReadLinesFromFile File="c:\temp2.txt">
<Output TaskParameter="Lines" ItemName="FolderNames" />
</ReadLinesFromFile>
My whole target looks like this:
<Target Name="Build">
<Exec Command="dir c:\temp2 /s /b > c:\temp2.txt" />
<ReadLinesFromFile File="c:\temp2.txt">
<Output TaskParameter="Lines" ItemName="LinesReadFromFile" />
</ReadLinesFromFile>
<Message Text="@(LinesReadFromFile)" Importance="low" />
</Target>
@(LinesReadFromFile) contains all the files and folders (empty or not) under the root folder you specify.
This is the only way of doing this I can think of right now.
cheers,
Stephane
AquaLunger
Vojtech
We talked about this in the team too, and unfortunately Stephane's approach is the only one you can do right now. It's kinda ugly, but it will work.
Neil