Condition using File :: Exists not working

I am currently creating my first MSBuild-script.

I have a "Folders" tag that finds all directories in a given root path:

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
  <Target Name="Build">
    <PropertyGroup>
      <RootFolder>tmp</RootFolder>
    </PropertyGroup>
    <ItemGroup>
      <Folders Include="$([System.IO.Directory]::GetDirectories(&quot;$(RootFolder)&quot;))"/>
    </ItemGroup>
    <Message Text="@(Folders -> '%(FullPath)\Bin\Debug\%(Filename)%(Extension).dll', ';')"/>
  </Target>
</Project>

      

This works great. My problem is that I only want the directories where the specified file is listed. I tried a condition like this

Condition="$([System.IO.File]::Exists(&quot;%(FullPath)\\Bin\\Debug\\%(Filename)%(Extension).dll&quot;))"

      

for the folder tag.

This script runs without error, but my list is empty. Why?

Are there any other solutions to validate the file?

I used this solution because it uses C # and I am a C # developer.

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
  <Target Name="Build">
    <PropertyGroup>
      <RootFolders>tmp</RootFolders>
    </PropertyGroup>
    <GetFiles rootFolders="$(RootFolders)">
      <Output PropertyName="Files" TaskParameter="Files" />
    </GetFiles>
    <Message Text="$(Files)" />
  </Target>

  <UsingTask
      TaskName="GetFiles"
      TaskFactory="CodeTaskFactory"
      AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
      <ParameterGroup>
        <rootFolders ParameterType="System.String" Required="true" />
        <files ParameterType="System.String" Output="true" />
      </ParameterGroup>
      <Task>
          <Using Namespace="System" />
          <Using Namespace="System.IO" />
          <Using Namespace="System.Linq" />
          <Code Type="Fragment" Language="cs">
              <![CDATA[               
                  Func<string, string> BuildFilePath = path => path + @"\Bin\Debug\" + Path.GetFileName(path) + ".dll";
                  var dirs = Directory.GetDirectories(rootFolders).Where(x => File.Exists(BuildFilePath(x)));
                  files = string.Join("\n", dirs.Select(BuildFilePath));
              ]]>
          </Code>
      </Task>
  </UsingTask>
</Project>

      

+3


source to share


1 answer


AFAIK, the thing Condition

is executed and checked for the entire element declaration (i.e. tag <Folders ..>

).

I think you need to go through the collection (using a target / batch job for example) and check if the file exists in each folder of the folder in the collection. Then, if the file exists, include it in the new item collection <FoldersFiletered>

.



NB: I don't have time to test the code now, but this is an idea roughly:

<Target Name="FilterFolders"
    Inputs="@(Folders)"
    Outputs="%(FullPath)">
    <ItemGroup>
    <FoldersFiltered Include="@(Folders->'%(FullPath)')"
        Condition="$([System.IO.File]::Exists(&quot;@(Folders->'%(FullPath)'\\Bin\\Debug\\YourFile.dll&quot;))" />
    </ItemGroup>
</Target>

      

+1


source







All Articles