Czy istnieje sposób automatycznego dołączania plików zawartości do pliku projektu asp.net?

86

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?

Marko
źródło
zobacz: to może pomóc ci stackoverflow.com/questions/1743432/…
Saar
1
nie do końca to, czego szukam
Marko
Zaktualizowałem moją odpowiedź dotyczącą Twojego problemu podczas modyfikowania folderu w przeglądarce vs Solution.
Filburt

Odpowiedzi:

134

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.

Chris
źródło
Jakie jest znaczenie .less? A co oznacza cały sznurek **\*.less?
Zarejestrowany użytkownik
3
Pliki .less to pliki css przeznaczone do analizowania przez preprocesor Less CSS. Google „kropka mniej”, aby uzyskać więcej informacji na ten temat. Wyrażenie **\*.lessoznacza obejmuje wszystkie pliki * .less we wszystkich katalogach. W języku MSBUILD ** oznacza „wszystkie katalogi rekurencyjnie”
Chris
4
Przynajmniej w VS 2012, gdy tylko dodasz / usuniesz plik z projektu i zapiszesz, niestety zostanie on rozszerzony do pełnej listy. :(
Chris Phillips
3
To zadziałało w mojej sytuacji dopiero po zmianie BeforeBuild na AfterBuild, moja kompilacja uruchamia skrypt PowerShell, który przenosi pliki, które następnie nie zostałyby odebrane przez moją próbę wdrożenia w sieci Azure, ponieważ istniały one dopiero po pomyślnym zakończeniu kompilacji. Widząc „BeforeBuild” dowiedziałem się, że prawdopodobnie istnieje również „AterBuild”. Mam nadzieję, że to pomoże komuś innemu.
Luke Rice
1
@John, zobacz moją odpowiedź poniżej, aby naprawić VS2015 +.
Jesse
54

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 CreateItemzadanie. 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.

Filburt
źródło
3
Działa do momentu ręcznego dodania lub usunięcia pliku. Następnie wiersz <Content Include = "Images * *. " /> Znika z pliku projektu.
Marko,
2
@Marko ma rację. Po dodaniu <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.
Ravi Ram
Umieść ten kod w oddzielnym pliku .proj i wywołaj go z celu przed kompilacją w pliku .csproj.
NL - Przeproś Monikę
21

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 rozszerzeniem ext w katalogu najwyższego poziomu, ale nie w podkatalogach
    • Na przykład, *.extmoże być *.png, *.jsitd Wszelkie rozszerzenie pliku będzie działać
  • **\*.extbędzie zawierać wszystkie pliki z rozszerzeniem extz katalogu najwyższego poziomu i wszystkich podkatalogów.
  • Zobacz odpowiedź w artykule Jak używać wzorców nazewnictwa Nant / Ant? aby uzyskać pełniejsze wyjaśnienie z przykładami.

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>
Jesse
źródło
1
Dzięki za eksperymentowanie i wskazanie różnic między używaniem <Cel> a nie. Świetne wyjaśnienie szczegółów symboli wieloznacznych.
Kurt Hutchinson
@KurtHutchinson - nie ma problemu. =)
Jesse
Uważam, że to rozwiązanie wymaga dopracowania. Kiedy nakazujesz docelowi biegać po "BeforeBuild", teoretycznie może to również nastąpić PO opublikowaniu. Obecne rozwiązanie prawdopodobnie działa na szczęście.
Imre Pühvel
@ ImrePühvel jak można dowiedzieć publikuje się dzieje przed tym BeforeBuildwydarzeniu? MSBuild musi najpierw skompilować projekt i pliki binarne, zanim będzie mógł nawet rozważyć publikację.
Jesse
1
Nie twierdziłem, że publikowanie miało miejsce przed kompilacją, ale deklaracja nie gwarantuje, że elementy zostaną dodane do treści przed opublikowaniem. Z próbki kodu: .. 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.aspx
Imre Pühvel
10

Moż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>
Steven Liekens
źródło
To była dla mnie duża pomoc; Mam wiele katalogów o kilku poziomach głębokości i wiele plików, które chciałem automatycznie dołączyć, a to zmieniło całą zawartość w jedną. Dzięki!
Jay Otterbein
2
Trochę więcej z tym eksperymentowałem i okazuje się, że ma to takie same ograniczenia, jak w Include="**\*.ext"przypadku symboli wieloznacznych.
Steven Liekens,
Wow, czy plik projektu zawiera uruchamianie programu PowerShell? Czy to w ogóle jest piaskownica? To exploit, który czeka, by się wydarzyć.
Brain2000
To nie jest PowerShell. MSBuild ma własną składnię do wywoływania metod statycznych. Według dokumentacji jest to ograniczone do klas systemowych. docs.microsoft.com/en-us/visualstudio/msbuild/ ... Chociaż jestem pewien, że możesz po prostu <Exec> powershell z dowolnymi argumentami ...
Steven Liekens
3

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

thom schumacher
źródło
2

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.

chongo2002
źródło
1
Próbowałem tego i VS zastępuje symbol wieloznaczny pojedynczymi plikami, gdy dodam lub usuwam plik za pomocą VS.
carlin.scott
To bardzo eleganckie, ale powinieneś usunąć symbol wieloznaczny z celu linku
SimSimY
1

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.

kamranicus
źródło
-1

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.

Marcin Skoczylas
źródło