Często dodaję wiele plików zawartości (głównie obrazów i js) do mojego projektu ASP.NET. Używam systemu publikowania VS, a podczas publikowania nowe pliki nie są publikowane, dopóki nie dołączę ich do projektu. Chciałbym automatycznie dołączyć wszystkie pliki w określonym katalogu. Czy istnieje sposób określenia, które katalogi powinny być automatycznie dołączane do pliku csproj lub gdziekolwiek indziej?
86
Odpowiedzi:
Wiem, że to stary wątek, ale znalazłem sposób, aby to zrobić, o którym ciągle zapominam, i szukając go po raz ostatni, natknąłem się na to pytanie. Najlepszym sposobem, jaki znalazłem, jest użycie celu BeforeBuild w pliku .csproj.
<Target Name="BeforeBuild"> <ItemGroup> <Content Include="**\*.less" /> </ItemGroup> </Target>
VS 2010 nie dotknie tej sekcji i zapewnia, że pliki są dołączane jako zawartość za każdym razem, gdy projekt jest budowany.
źródło
**\*.less
?**\*.less
oznacza obejmuje wszystkie pliki * .less we wszystkich katalogach. W języku MSBUILD ** oznacza „wszystkie katalogi rekurencyjnie”Możesz po prostu rozszerzyć plik .csproj swojej witryny. Po prostu dodaj folder główny zawartości za pomocą rekursywnego symbolu wieloznacznego:
... <ItemGroup> <!-- your normal project content --> <Content Include="Default.aspx" /> <!-- your static content you like to publish --> <Content Include="Images\**\*.*" /> </ItemGroup> ...
Dzięki temu ten folder i cała zawartość poniżej będą widoczne w przeglądarce rozwiązań.
Jeśli spróbujesz ukryć folder w przeglądarce rozwiązań, określając
<Content Include="Images\**.*.*"> <Visible>false</Visible> </Content>
nie zostanie opublikowany.
Aktualizacja
Jak już odkryłeś, symbol wieloznaczny zostanie zastąpiony, gdy tylko dotkniesz folderu wewnątrz rozwiązania, ponieważ projekty VS nie są zaprojektowane tak, aby zawierały dowolną zawartość.
Będziesz więc musiał upewnić się, że folder i jego zawartość nigdy nie są modyfikowane z poziomu VS - dodawanie lub usuwanie plików można wykonać tylko w systemie plików ... co chciałeś, jak zrozumiałem twoje pytanie.
Byłoby łatwiej, gdyby folder można było ukryć w VS, ale nie mogłem znaleźć sposobu, aby go ukryć ORAZ opublikować.
Innym nieudanym podejściem było dołączenie folderu przez
CreateItem
zadanie. Spowodowało to, że zawartość folderu została opublikowana w \ bin \ app.publish \ ... i nie mogłem się przekonać do opublikowania go razem z elementami zawartości wewnątrz .csproj, więc nie przedstawiłem tego w mojej odpowiedzi.źródło
<Content Include="Images\**\*.*" />
zadziałało. Po dodaniu większej liczby obrazów .csproj zostaje zmieniony i wraca do wyświetlania wszystkich plików w images / ..., a <Content Include = "Images * *. " /> Znika.Dla tych, którzy mają problemy z używaniem odpowiedzi Chrisa , jest to rozwiązanie dla programu Visual Studio 2012 i nowszych:
<Target Name="ContentsBeforeBuild" AfterTargets="BeforeBuild"> <ItemGroup> <Content Include="images\**" /> </ItemGroup> </Target>
Jak wspomniał Chris w swojej odpowiedzi - Visual Studio nie dotknie tej
<Target>
sekcji, nawet jeśli ręcznie bawisz się (dodając / usuwając pliki) z katalogiem docelowym.Pamiętaj, że ty powinieneś dołączyć podkatalog, w którym znajdują się pliki (w powyższym przypadku jest to
images
). Visual Studio / MSBuild umieści te pliki w tym samym katalogu w strukturze projektu. Jeśli nie używasz podkatalogu, pliki zostaną umieszczone w katalogu głównym struktury projektu.Szybkie wyjaśnienie symboli wieloznacznych:
**
znaczy wszystko rekurencyjnie (pliki, podkatalogi i pliki w nich)*.ext
będzie zawierać wszystkie pliki z rozszerzeniemext
w katalogu najwyższego poziomu, ale nie w podkatalogach*.ext
może być*.png
,*.js
itd Wszelkie rozszerzenie pliku będzie działać**\*.ext
będzie zawierać wszystkie pliki z rozszerzeniemext
z katalogu najwyższego poziomu i wszystkich podkatalogów.Aby zakończyć, pamiętaj, że istnieje różnica między używaniem
<Target>
a nie korzystaniem z niego.Przy takim
<Target>
podejściu program Visual Studio nie wyświetli plików w Eksploratorze rozwiązań.<Target Name="ContentsBeforeBuild" AfterTargets="BeforeBuild"> <ItemGroup> <Content Include="images\**" /> </ItemGroup> </Target>
To
<Target>
podejście nie spowoduje, że program Visual Studio pokaże pliki w Eksploratorze rozwiązań. Wadą tego jest to, że jakakolwiek manipulacja automatycznymi katalogami spowoduje, że program Visual Studio przesłoni wpis wieloznaczny. Należy również zauważyć, że poniższe podejście spowoduje aktualizację Eksploratora rozwiązań dopiero po otwarciu rozwiązania / projektu w VS. Nawet przycisk „odśwież” paska narzędzi w Eksploratorze rozwiązań tego nie zrobi.<ItemGroup> <Content Include="images\**" /> </ItemGroup>
źródło
BeforeBuild
wydarzeniu? MSBuild musi najpierw skompilować projekt i pliki binarne, zanim będzie mógł nawet rozważyć publikację... AfterTargets="BeforeBuild"
. Oznacza to, że Twój cel niestandardowy musi zostać wykonany po BeforeBuild, ale nie określa, ile po. Chociaż, mój błąd, według obecnego algorytmu porządkowania celu powinno być ok: msdn.microsoft.com/en-us/library/ee216359.aspxMożesz użyć metody struktury
System.IO.Directory.GetFile(string)
i jej przeciążeń, aby rekurencyjnie dołączyć wszystkie pliki.<ItemGroup> <Content Include="$([System.IO.Directory]::GetFiles('$(ProjectDir)Scripts\', '*.js', SearchOption.AllDirectories))" /> <Content Include="$([System.IO.Directory]::GetFiles('$(ProjectDir)Images\', '*.png', SearchOption.AllDirectories))" /> </ItemGroup>
źródło
Include="**\*.ext"
przypadku symboli wieloznacznych.Napisałem, w jaki sposób udało mi się uzyskać zawartość utworzoną za pomocą małego skryptu PowerShell:
$folders = Get-ChildItem .\ -r -Directory $filtered = $folders |Select-Object @{Name='FullName';Expression={$_.fullname.replace($pwd,'')}}, @{Name='FolderDepth';Expression={($_.fullname.Split('\').Count) - ($Pwd.Path.split('\').count)}} | Sort-Object -Descending FullName,folderDepth $basefolders = $filtered | Where-Object{$_.folderdepth -eq 1} $basefoldersobj = @() foreach($basefolder in $basefolders) { $basefoldername =$baseFolder.fullname $filteredbase = $filtered -match "\$basefoldername\\" | Sort-Object -Descending FolderDepth | Select-Object -first 1 if($filteredbase -eq $null) { $filteredbase = $filtered -match "\$basefoldername" | Sort-Object -Descending FolderDepth | Select-Object -first 1 } $obj = New-Object psobject Add-Member -InputObject $obj -MemberType NoteProperty -Name 'Folder' -Value $basefolder.fullname.trim('\') Add-member -InputObject $obj -MemberType NoteProperty -Name 'DeepestPath' -Value $filteredbase.folderDepth $basefoldersobj += $obj } $include = '*.*' foreach($bfolderObj in $basefoldersobj) { $includecount = '' $includecount = "\$include" * ($bfolderObj.Deepestpath) Write-Output "<content Include=`"$($bfolderObj.folder)$includecount`" /> " }
Powinno to spowodować wyświetlenie niezbędnej instrukcji include w wierszu polecenia programu PowerShell
źródło
Możesz dodawać pliki z takimi linkami, można je przeszukiwać, wyświetlać, ale nie są pobierane, jeśli spróbujesz je zmienić, również Visual Studio pozostawia symbole wieloznaczne na miejscu:
<ItemGroup> <Content Include="..\Database Schema\Views\*.sql"> <Link>Views\*.sql</Link> </Content> </ItemGroup>
To znajduje się w pliku .proj.
źródło
Nic mi nie wiadomo; jednak moja sugestia jest taka, aby wkleić je do projektu, ponieważ będzie to obejmować je domyślnie. Dlatego zamiast wklejać je do katalogu za pomocą Eksploratora, użyj programu Visual Studio, aby wkleić pliki do folderów.
źródło
Zdałem sobie sprawę, że najlepszym rozwiązaniem jest ręczne dodawanie plików, jeden po drugim. Jeśli masz ich setki, tak jak ja, to kwestia kilku godzin. Zabawne, że nawet w 2016 roku z VS 2015 ten poważny problem nie został rozwiązany. Ach, jak bardzo kocham Xcode.
źródło