2009-12-19 6 views
3

확장명에 관계없이 특정 이름의 파일을 제외하면서 특정 디렉터리의 모든 파일에서 ItemGroup을 생성하려고하는 스크립트가 있습니다.MSBuild : 별표 및 이상한 ItemGroup 동작 제외

제외 할 파일 목록에는 파일 확장명이 포함되어 있으며 확장명을 별표로 바꾸려면 커뮤니티 작업 'RegexReplace을 사용하고 있습니다. 그런 다음 항목의 Exclude 속성에서이 목록을 사용합니다. 어떤 이유로 파일이 올바르게 표시되지 않아도 파일이 제대로 제외되지 않습니다.

원인을 찾으려면 두 가지 작업이있는 테스트 스크립트 (아래)를 작성해야합니다. 첫 번째는의 파일 패턴 목록을 사용하여 두 가지 속성을 초기화합니다. 두 번째 작업은 두 속성과 Exclude 특성에서이 속성을 모두 사용하여 생성 된 파일을 모두 인쇄합니다.

속성 값은 동일하지만 결과 그룹은 다릅니다. 이것이 어떻게 가능한지? (명확성을 위해 다소 포맷)

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" 
     DefaultTargets="Init;Test" ToolsVersion="3.5"> 
    <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/> 

    <Target Name="Init"> 
    <ItemGroup> 
     <OriginalFilenames Include="TestDir\SampleProj.exe"/> 
     <OriginalFilenames Include="TestDir\SampleLib1.dll"/> 
    </ItemGroup> 
    <RegexReplace Input="@(OriginalFilenames)" Expression="\.\w+$" Replacement=".*"> 
     <Output TaskParameter="Output" ItemName="PatternedFilenames"/> 
    </RegexReplace> 
    <PropertyGroup> 
     <ExcludeFilesA>TestDir\SampleProj.*;TestDir\SampleLib1.*</ExcludeFilesA> 
     <ExcludeFilesB>@(PatternedFilenames)</ExcludeFilesB> 
    </PropertyGroup> 
    </Target> 

    <Target Name="Test"> 
    <Message Text='ExcludeFilesA: $(ExcludeFilesA)' /> 
    <Message Text='ExcludeFilesB: $(ExcludeFilesB)' /> 
    <ItemGroup> 
     <AllFiles Include="TestDir\**"/> 
     <RemainingFilesA Include="TestDir\**" Exclude="$(ExcludeFilesA)"/> 
     <RemainingFilesB Include="TestDir\**" Exclude="$(ExcludeFilesB)"/> 
    </ItemGroup> 
    <Message Text="&#xA;**AllFiles**&#xA;@(AllFiles, '&#xA;')" /> 
    <Message Text="&#xA;**PatternedFilenames**&#xA;@(PatternedFilenames, '&#xA;')" /> 
    <Message Text="&#xA;**RemainingFilesA**&#xA;@(RemainingFilesA, '&#xA;')" /> 
    <Message Text="&#xA;**RemainingFilesB**&#xA;@(RemainingFilesB, '&#xA;')" /> 
    </Target> 

</Project> 

출력 :

ExcludeFilesA: TestDir\SampleProj.*;TestDir\SampleLib1.* 
ExcludeFilesB: TestDir\SampleProj.*;TestDir\SampleLib1.* 

AllFiles: 
    TestDir\SampleLib1.dll 
    TestDir\SampleLib1.pdb 
    TestDir\SampleLib2.dll 
    TestDir\SampleLib2.pdb 
    TestDir\SampleProj.exe 
    TestDir\SampleProj.pdb 

PatternedFilenames: 
    TestDir\SampleProj.* 
    TestDir\SampleLib1.* 

RemainingFilesA: 
    TestDir\SampleLib2.dll 
    TestDir\SampleLib2.pdb 

RemainingFilesB: 
    TestDir\SampleLib1.dll 
    TestDir\SampleLib1.pdb 
    TestDir\SampleLib2.dll 
    TestDir\SampleLib2.pdb 
    TestDir\SampleProj.exe 
    TestDir\SampleProj.pdb 

ExcludeFilesAExcludeFilesB과 모두 동일 보이는 것을 관찰되지만, 생성 그룹 RemainingFilesARemainingFilesB와는 다르다.

궁극적으로 ExcludeFilesB과 같은 방식으로 생성 된 패턴을 사용하여 RemainingFilesA 목록을 얻고 싶습니다. 방법을 제안 할 수 있습니까, 아니면 완전히 제 접근 방식을 재고해야합니까?

답변

2

.

ExcludeFilesA의 실제 값은 예상 할 수있는 것처럼 TestDir\SampleProj.*;TestDir\SampleLib1.*입니다. 그러나 ExcludeFilesB의 실제 값은 TestDir\SampleProj.%2a;TestDir\SampleLib1.%2a입니다.

아마도 Message은 문자열을 사용하기 전에 이스케이프 처리하지 않지만 IncludeExclude은 그렇지 않습니다. 그러면 문자열이 왜 똑같이 보이지만 다르게 동작하는지 설명 할 수 있습니다.

덧붙여 말하자면, 실행 순서는 이것과 관련이없는 것처럼 보이며 모든 것이 실행되고 정확하게이 스크립트에 나타나는 순서대로 평가된다는 것이 확실합니다.

+0

위대한 catch ... 좋은 하나! – KMoraz

+0

대단히 감사합니다! 사실, 별표를''에서 별표를 사용하지 않고 나중에 파일 격언없이 그대로 가져 오려고했지만 그 정보를 찾을 수 없었습니다. 당신의 연구가 나를 도와주었습니다 - '% 2a'를 사용하면 확장 기능이 꺼지고 나중에 명령에서 모든 '@ -'변환에 별표가 생겼습니다. – quetzalcoatl

+0

aand이 주석을 작성한 직후 https://docs.microsoft.com/en-us/visualstudio/msbuild/special-characters-to-escape에 포함되어 있으며 명시 적으로 Include와 asterisk가 지적되었습니다. – quetzalcoatl

0

대상 그룹을 실행하기 전에 대상 그룹을 평가해야하며 PatternedFilenames ItemGroup이 대상 컨테이너 내에서 즉시 작성되어야합니다. 당신은 실행에 걸쳐 PatternedFilenames 범위를 보장합니다 CreateItem 작업을 사용하여이 문제를 해결 할 수 : 사용자 지정 작업은 예외를 던질 때 이것의 진정한 원인은 실수로 밝혀졌다

<RegexReplace Input="@(OriginalFilenames)" Expression="\.\w+$" Replacement=".*"> 
    <Output TaskParameter="Output" ItemName="PatternedFilenames_tmp"/> 
</RegexReplace> 
<CreateItem Include="@(PatternedFilenames_tmp)"> 
    <Output TaskParameter="Include" ItemName="PatternedFilenames"/> 
</CreateItem> 
+0

해결 방법을 알려 주셔서 감사합니다. 상황이 더 자세하게 설명되는 순서를 설명해 주시겠습니까? 분명히 'ExcludeFilesA'는 ItemGroup'RemainingFilesA'가 생성되기 전에 초기화됩니다; 어떻게 RemainingFilesB'에 대해서도 같은 일이 일어나지 않을까요? 그것은 거의 순서처럼 보입니다 : 1. "Init"가 끝납니다; 2. 평가 된 "테스트"의 ItemGroups. 3. RegexReplace가 평가되었습니다. 4. "테스트"가 시작되고 메시지를 인쇄합니다. 하지만 분명히 그렇게 될 수는 없어? ... –

+0

여기에서 "속성 및 항목 평가 주문"섹션을 읽어보십시오. http://msdn.microsoft.com/en-us/library/dd997067(VS.100).aspx 이 게시물은 문제와 관련이 있습니다. http :// /elegantcode.com/2006/12/11/msbuild-items-run-time-evaluation-behavior/ – KMoraz