2010-10-08 110 views
6

問題:根據exclude屬性中傳遞的值,ItemGroups數組未正確構建。MSBuild ItemGroup包含/排除模式問題

如果您運行此腳本創建了一些示例文件,然後嘗試基於Include/Exclude屬性創建一個名爲TheFiles的數組,則問題是排除是硬編碼以外的任何內容或非常簡單的屬性時,它會導致錯誤。

目標DynamicExcludeList的不正確選擇這些文件:
\ AFolder \ test.cs中; \ AFolder \ test.txt的

目標HardcodedExcludeList的正確選擇這些文件:。
\ AFolder \ test.txt的。

任何幫助非常感謝,這是讓我瘋了。

(注意其的msbuild V4)

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Run"> 

     <Target Name="Run" > 
     <CallTarget Targets="CreateSampleFiles" /> 
     <CallTarget Targets="DynamicExcludeList" /> 
     <CallTarget Targets="HardcodedExcludeList" /> 
     </Target> 

     <Target Name="CreateSampleFiles" > 
     <MakeDir Directories="AFolder" /> 
     <WriteLinesToFile Lines="Test" File="AFolder\test.cs" Overwrite="true" /> 
     <WriteLinesToFile Lines="Test" File="AFolder\test.txt" Overwrite="true" /> 
     </Target> 

     <Target Name="DynamicExcludeList" > 

     <PropertyGroup> 
      <CommonFileExclusion>.\DIRECTORY_NAME_TOKEN\**\*.cs</CommonFileExclusion> 
      <FinalExcludes>$(CommonFileExclusion.Replace('DIRECTORY_NAME_TOKEN', 'AFolder'))</FinalExcludes> 
     </PropertyGroup> 

     <Message Text="FinalExcludes: $(FinalExcludes)" /> 
     <ItemGroup> 
      <TheFiles 
      Include=".\AFolder\**\*;" 
      Exclude="$(FinalExcludes)" 
      /> 
     </ItemGroup> 
     <Message Text="TheFiles: @(TheFiles)" /> 

     </Target> 

     <Target Name="HardcodedExcludeList" > 

     <PropertyGroup> 
      <FinalExcludes>.\AFolder\**\*.cs</FinalExcludes> 
     </PropertyGroup> 

     <Message Text="FinalExcludes: $(FinalExcludes)" /> 
     <ItemGroup> 
      <TheFilesWithHardcodedExcludes 
      Include=".\AFolder\**\*;" 
      Exclude="$(FinalExcludes)" 
      /> 
     </ItemGroup> 
     <Message Text="TheFilesWithHardcodedExcludes: @(TheFilesWithHardcodedExcludes)" /> 

     </Target> 
    </Project> 

這是輸出,請注意 'TheFiles' 和 'TheFilesWithHardcodedExcludes'

 
PS C:\SVN\TrunkDeployment\TestMsBuild> msbuild .\Test.build.xml 
Microsoft (R) Build Engine Version 4.0.30319.1 
[Microsoft .NET Framework, Version 4.0.30319.1] 
Copyright (C) Microsoft Corporation 2007. All rights reserved. 

Build started 8/10/2010 2:30:42 PM. 
Project "C:\SVN\TrunkDeployment\TestMsBuild\Test.build.xml" on node 1 (default targets). 
DynamicExcludeList: 
    FinalExcludes: .\AFolder\**\*.cs 
    TheFiles: .\AFolder\test.cs;.\AFolder\test.txt 
HardcodedExcludeList: 
    FinalExcludes: .\AFolder\**\*.cs 
    TheFilesWithHardcodedExcludes: .\AFolder\test.txt 
Done Building Project "C:\SVN\TrunkDeployment\TestMsBuild\Test.build.xml" (default targets). 


Build succeeded. 
    0 Warning(s) 
    0 Error(s) 

Time Elapsed 00:00:00.06 

EDITS之間的差異

I」已經更新了上面的腳本以使用CreateItem,但是當項目列表t仍然存在問題時排除包含多於一個路徑(即, CommonFileExclusion的值更改):

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Run"> 

     <Target Name="Run" > 
     <CallTarget Targets="CreateSampleFiles" /> 
     <CallTarget Targets="DynamicExcludeList" /> 
     <CallTarget Targets="HardcodedExcludeList" /> 
     </Target> 

     <Target Name="CreateSampleFiles" > 
     <MakeDir Directories="AFolder" /> 
     <WriteLinesToFile Lines="Test" File="AFolder\test.cs" Overwrite="true" /> 
     <WriteLinesToFile Lines="Test" File="AFolder\test.txt" Overwrite="true" /> 
     <WriteLinesToFile Lines="Test" File="AFolder\test.vb" Overwrite="true" /> 
     </Target> 

     <Target Name="DynamicExcludeList" > 

     <PropertyGroup> 
      <CommonFileExclusion>.\DIRECTORY_NAME_TOKEN\**\*.cs;.\DIRECTORY_NAME_TOKEN\**\*.vb;</CommonFileExclusion> 
      <FinalExcludes>$(CommonFileExclusion.Replace('DIRECTORY_NAME_TOKEN', 'AFolder'))</FinalExcludes> 
     </PropertyGroup> 

     <Message Text="FinalExcludes: $(FinalExcludes)" /> 
     <CreateItem Include=".\AFolder\**\*;" 
        Exclude="$(FinalExcludes)"> 
      <Output TaskParameter="Include" ItemName="TheFiles"/> 
     </CreateItem> 
     <Message Text="TheFiles: @(TheFiles)" /> 

     </Target> 

     <Target Name="HardcodedExcludeList" > 

     <PropertyGroup> 
      <FinalExcludes>.\AFolder\**\*.cs;.\AFolder\**\*.vb</FinalExcludes> 
     </PropertyGroup> 

     <Message Text="FinalExcludes: $(FinalExcludes)" /> 
     <CreateItem Include=".\AFolder\**\*;" 
        Exclude="$(FinalExcludes)"> 
      <Output TaskParameter="Include" ItemName="TheFilesWithHardcodedExcludes"/> 
     </CreateItem> 
     <Message Text="TheFilesWithHardcodedExcludes: @(TheFilesWithHardcodedExcludes)" /> 

     </Target> 
    </Project> 

回答

14

好的,我試了一下,我認爲問題來自於你使用一個屬性代表多個值的SCALAR值。我會建議配料和改造(見http://scottlaw.knot.org/blog/?p=402http://msdn.microsoft.com/en-us/library/ms171476.aspx)。例如,下面的代碼正在工作:

<Target Name="DynamicExcludeList" > 
    <ItemGroup> 
    <ExtensionsExcluded Include="cs;vb" /> 
    </ItemGroup> 

    <CreateItem Include=".\AFolder\**\*" 
      Exclude="@(ExtensionsExcluded->'.\AFolder\**\*.%(identity)')"> 
    <Output TaskParameter="Include" ItemName="TheFiles"/> 
    </CreateItem> 
    <Message Text="TheFiles: @(TheFiles)" /> 
</Target> 
+0

感謝您的修復,它只是MSBuild(IMO)中令人討厭的那些東西之一,因爲它變得越複雜,您要添加的排除越多(例如某些目錄中的某些文件,而不是其他等),可能會尋找另一種解決方案。 – Keith 2010-10-11 07:54:42

2

在目標DynamicExcludeList使用CreateItem任務,而不是ItemGroup動態生成您的項目:

<Target Name="DynamicExcludeList" > 

    <PropertyGroup> 
    <CommonFileExclusion>.\DIRECTORY_NAME_TOKEN\**\*.cs</CommonFileExclusion> 
    <FinalExcludes>$(CommonFileExclusion.Replace('DIRECTORY_NAME_TOKEN', 'AFolder'))</FinalExcludes> 
    </PropertyGroup> 

    <Message Text="FinalExcludes: $(FinalExcludes)" /> 

    <CreateItem Include=".\AFolder\**\*;" 
       Exclude="$(FinalExcludes)"> 
    <Output TaskParameter="Include" ItemName="TheFiles"/> 
    </CreateItem> 

    <Message Text="TheFiles: @(TheFiles)" /> 
</Target> 

理論上ItemGroupCreateItem是等價的,但我已經看到了像這樣的情況(動態情況)CreateItem必須使用。

+1

事實上,在每個目標運行之前,腳本解析時都會評估屬性和項目組。這就是爲什麼你的項目組沒有填充你的想法,而是你的msbuild腳本執行之前的內容。您可以在這裏閱讀更多信息:http://blogs.msdn.com/b/msbuild/archive/2006/01/03/508629.aspx和http://www.sedodream.com/PermaLink,guid,dd6cb1db- c0e4-47f7-ad84-6e59ff6b03d0.aspx。避免此問題的一個好方法是在目標外部使用ItemGroup(用於靜態項目)和createitem(用於動態項目) – 2010-10-08 14:17:48

+0

感謝您的解釋。但是,如果您查看CreateItem(http://msdn.microsoft.com/en-us/library/s2y3e43x.aspx)上的文檔,您會看到此任務已被棄用,因此您可以認爲目標中的ItemGroup將被評估動態地像CreateItem一樣。 – 2010-10-08 14:20:58

+0

感謝您的反饋,我仍然有一個問題(在一秒內發佈),根據這個:http://stackoverflow.com/questions/937681/createitem-vs-itemgroup,CreateItem在3中已經過時。5 – Keith 2010-10-08 14:23:18