简体   繁体   中英

Copy linked content files at each build using MSBuild with certain constraints

I am using Sharing files with Visual Studio's linked files concept. So I need to do Copy linked content files at each build using MSBuild.

For doing that I have written this code in my .vbproj file inside Project tag.

 <Target Name="CopyLinkedContentFiles" BeforeTargets="Build">
 <Copy SourceFiles="%(Content.Identity)" DestinationFiles=(Content.Identity)" 
 SkipUnchangedFiles="true" OverwriteReadOnlyFiles="true" 
 Condition="'@(AllFiles)' != ''" />
 </Target>

and it's working fine. all the linked files are being copied.

But here I need to add certain constraints eg 'not copying files with .vb extension' . How to achieve that ?

I have tried this code

 <Target Name="CopyLinkedContentFiles" BeforeTargets="Build">

 <CreateItem Include="%(Content.Identity)">
    <Output ItemName="AllFiles" TaskParameter="Include" />
 </CreateItem>

 <ItemGroup>
   <AllFiles Remove="@(AllFiles)" Condition="'%(Extension)' == '.vb'"/>
  </ItemGroup>

  <Copy SourceFiles="@(AllFiles)" DestinationFiles="@(AllFiles)" 
     SkipUnchangedFiles="true" OverwriteReadOnlyFiles="true" 
     Condition="'@(AllFiles)' != ''" />
  </Target>   

Its not working.No file is being copied.Please suggest any idea.

The way you are removing items should work. But the Copy task's SourceFiles and DestinationFiles are the same in the code you show so that's obviously a null operation. Use something like this instead:

<Copy SourceFiles="@(AllFiles)" DestinationFolder="$(MyDestDir)" />

Or, if the destination filenames depend on the input filenames:

<Target Name="MyCopy">
  <ItemGroup>
    <AllFiles Include="%(Content.Identity)" Condition="'%(Extension)' != '.vb'">
      <!-- Add metadata which will be used as destination directory:
           strip point from extension and convert to uppercase -->
      <Ext>$([System.String]::Copy('%(Extension)').Replace('.','').ToUpper())</Ext>
    </AllFiles>
  </ItemGroup>

  <Copy SourceFiles="@(AllFiles)"
        DestinationFiles="@(AllFiles->'$(OutDir)\%(Ext)\%(Filename)%(Extension)')" />
</Target>

You don't need the check for AllFiles being empty: if it is, nothing will be copied.

As you can see I used an easier and shorter way to achieve the filtering of items: with Remove you always need two statements, using just a Condition on the extension you just need one. For the sake of completeness here are 4 different ways including yours, but the first one being the shortest (also note you don't neeed CreateItem, just use an Item: less typing, same effect):

<ItemGroup>
  <Content Include="a.foo;b.foo;a.vb;b.vb"/> <!-- sample items -->
</ItemGroup>

<Target Name="FilterExamples">
  <ItemGroup>
   <AllFilesUsingCondition Include="%(Content.Identity)" Condition="'%(Extension)' != '.vb'"/>

   <VbFiles Include="%(Content.Identity)" Condition="'%(Extension)' == '.vb'"/>
   <AllFilesUsingExclude Include="%(Content.Identity)" Exclude="@(VbFiles)"/>

   <AllFilesUsingRemove Include="%(Content.Identity)"/>
   <AllFilesUsingRemove Remove="@(VbFiles)"/>

   <AllFilesUsingRemoveCondition Include="%(Content.Identity)"/>
   <AllFilesUsingRemoveCondition Remove="@(AllFilesUsingRemoveCondition)" Condition="'%(Extension)' == '.vb'"/>
  </ItemGroup>

  <Message Text="AllFilesUsingCondition=@(AllFilesUsingCondition)" />
  <Message Text="AllFilesUsingExclude=@(AllFilesUsingExclude)" />
  <Message Text="AllFilesUsingRemove=@(AllFilesUsingRemove)" />
  <Message Text="AllFilesUsingRemoveCondition=@(AllFilesUsingRemoveCondition)" />
</Target>

Output:

AllFilesUsingCondition=a.foo;b.foo
AllFilesUsingExclude=a.foo;b.foo
AllFilesUsingRemove=a.foo;b.foo
AllFilesUsingRemoveCondition=a.foo;b.foo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM