2012-07-11 9 views
9

Próbuję uzyskać skrypt MSBuild do pracy w celu budowania i wyodrębniania do wdrożenia dość dużej aplikacji internetowej. (Mówimy tu o kilku tysiącach plików w kilkudziesięciu katalogach, tutaj jest to odziedziczony, stary kod źródłowy, więc niewiele mogę z tym zrobić). Sama kompilacja działa dobrze, ale nie mogę kopiować pliki do miejsca upuszczania działa poprawnie.Kopiowanie kompilacji plików wyjściowych, zachowanie struktury katalogów, daje "Nielegalne znaki na ścieżce"

Oto fragment pokazujący to, co mam w skrypcie produkcji:

<PropertyGroup Condition=" '$(UseBuildNumber)' == 'true' "> 
    <ReleaseDirectory>$(ReleaseBaseDirectory)$(ReleaseName)\$(BuildNumber)</ReleaseDirectory> 
</PropertyGroup> 

<ItemGroup> 
    <OutputFiles Include=" 
       $(SourceRoot)**\*.aspx; 
       $(SourceRoot)**\*.dll; 
       $(SourceRoot)**\*.gif; 
       $(SourceRoot)**\*.ascx; 
       " /> 
</ItemGroup> 

<Message Text="Output files ==> @(OutputFiles)" /> 

<Copy 
    SourceFiles="@(OutputFiles)" 
    DestinationFolder="$(ReleaseDirectory)" 
    SkipUnchangedFiles="false" 
    /> 

mam umieścić kilka dodatkowych <Message/> tam, aby upewnić się, że poszczególne ścieżki rozwijać prawidłowo, a zarówno $(SourceRoot) i $(ReleaseDirectory) rzeczywiście mają prawidłowe ścieżki. Jednak w produkcji, uzyskać pełną ścieżkę pomijana (dla uproszczenia):

Task "Message" 
    Output files ==> ...\Requirement1866**\*.aspx;...\Requirement1866**\*.dll;...\Requirement1866**\*.gif;...\Requirement1866**\*.ascx 
Done executing task "Message". 

Oczywiście ekspansja wieloznaczny nie zostało wykonane, a następnie po Copy (dość przewidywalny) nie powiedzie się. Załączam tylko jeden; w rzeczywistości jest to powtarzane dla każdego wzorca nazw plików (które z kolei są o wiele bardziej niż zawarte we fragmencie skryptu budowy powyżej).

Using "Copy" task from assembly "Microsoft.Build.Tasks.v3.5, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a". 
Task "Copy" 
    Copying file from "*basedir*\Requirement1866**\*.aspx" to "*targetdir*\Requirement1866\*buildnumber*\*.aspx". 
    Command: 
    copy /y "*basedir*\Requirement1866**\*.aspx" "*targetdir*\Requirement1866\*buildnumber*\*.aspx" 
d:\Builds\215\BuildType\TFSBuild.proj(120,5): error MSB3021: Unable to copy file "*basedir*\Requirement1866**\*.aspx" to "*targetdir*\Requirement1866\*buildnumber*\*.aspx". Illegal characters in path. 

następuje:

d:\Builds\215\BuildType\TFSBuild.proj(120,5): error MSB3021: Unable to copy file "*basedir*\Requirement1866**\*.aspx" to "*targetdir*\Requirement1866\*buildnumber*\*.aspx". Illegal characters in path. 

Jedyny rozsądnie istotne hitem mam natknąć w moich wysiłkach na Googling było Copy Task - Illegal characters in path, ale jestem już przy użyciu <ItemGroup> i przykład <CreateItem> (dostosowany) w ogóle nie działał, przerwał wcześnie z błędem mówiąc, że TaskParameter był nieznany (przepraszam, nie mam dokładnego komunikatu o błędzie przede mną).

Jako środek tymczasowy, mógłbym wejść i ręcznie skopiować odpowiednie pliki z katalogu wyjściowego kompilacji tam, gdzie chcę, ale chcę, aby proces ten był zautomatyzowany.

W jaki sposób za pomocą programu MSBuild skopiować pliki utworzone podczas procesu kompilacji do katalogu wyjściowego, zachowując względną strukturę katalogów, nie wymieniając ich pojedynczo?

+0

Nie mam bezpośredniej odpowiedzi, ale już napotkałem ten problem. Skończyłem na pisaniu skryptu PowerShell, aby to zrobić i nazwać go post-build action. Również +1 na to pytanie, ponieważ jest ono tak efektownie dobrze zbadane. Czekam na odpowiedź! – allquixotic

Odpowiedz

20

Zasadniczo ** jest pojedynczą ścieżkę elementowy, a zatem musi być odpowiednio ukośnikowe rozdzielany w dyrektywie Include:

<ItemGroup> 
    <OutputFiles Include=" 
       $(SourceRoot)\**\*.aspx; 
       $(SourceRoot)\**\*.dll; 
       $(SourceRoot)\**\*.gif; 
       $(SourceRoot)\**\*.ascx; 
       " /> 
</ItemGroup> 

zauważyć różnicę pomiędzy określając np $(SourceRoot)\**\*.aspx w przeciwieństwie do zepsutego $(SourceRoot)**\*.aspx. Jeśli $(SourceRoot) zakończyłoby się z \, rozszerzenie z użyciem symboli wieloznacznych prawdopodobnie również zadziałałoby na początku.

Po drugie, w <Copy/> użyć %(RecursiveDir):

<Copy 
    SourceFiles="@(OutputFiles)" 
    DestinationFolder="$(ReleaseDirectory)\%(RecursiveDir)" 
    SkipUnchangedFiles="false" 
    /> 

Z tych zmian, wydaje się działać tak jak chcę go do: pliki są kopiowane do zamierzonego katalogu docelowego, a struktura katalogów u źródła jest zachowany w docelowej lokalizacji.

2

Inną propozycją, zamiast dodawania opcji Includes dla każdego typu pliku, jest łatwe dodawanie wykluczeń.

<ItemGroup> 
    <OutputFiles Include="$(SourceRoot)**\*.*" Exclude="$(SourceRoot)**\*.cs;$(SourceRoot)**\*.resx" " /> 
</ItemGroup> 

W ten sposób dane wyjściowe będą zawierać dowolne wymagane typy JS, HTML, DHTML i inne typy plików.

+0

Oba podejścia działają, w zależności od potrzeb. W moim przypadku znacznie łatwiej było wyliczyć to, co chciałem skopiować, i po prostu wykluczyć wszystko inne. –

Powiązane problemy