Saya sering menambahkan banyak file konten (kebanyakan gambar dan js) ke proyek ASP.NET saya. Saya menggunakan sistem VS publish, dan saat mempublikasikan, file baru tidak dipublikasikan sampai saya memasukkannya ke dalam proyek. Saya ingin memasukkan semua file secara otomatis dalam direktori tertentu. Apakah ada cara untuk menentukan direktori mana yang harus otomatis disertakan dalam file csproj atau di mana pun?
88
Jawaban:
Untaian lama, saya tahu, tetapi saya menemukan cara untuk melakukan ini yang terus saya lupakan, dan dalam pencarian saya untuk menemukannya untuk terakhir kalinya, saya tersandung pada pertanyaan ini. Cara terbaik yang saya temukan untuk ini adalah dengan menggunakan target BeforeBuild di file .csproj.
<Target Name="BeforeBuild"> <ItemGroup> <Content Include="**\*.less" /> </ItemGroup> </Target>
VS 2010 tidak akan menyentuh bagian ini, dan memastikan bahwa file Anda disertakan sebagai konten setiap kali proyek dibuat.
sumber
**\*.less
?**\*.less
berarti menyertakan semua file * .less di semua direktori. Dalam bahasa MSBUILD, ** berarti 'semua direktori secara rekursif'Anda cukup memperluas file .csproj situs web Anda. Cukup tambahkan folder root konten Anda dengan wildcard rekursif:
... <ItemGroup> <!-- your normal project content --> <Content Include="Default.aspx" /> <!-- your static content you like to publish --> <Content Include="Images\**\*.*" /> </ItemGroup> ...
Melakukannya membuat folder ini dan semua konten di bawah terlihat di dalam browser solusi Anda.
Jika Anda mencoba menyembunyikan folder di dalam browser solusi dengan menentukan
<Content Include="Images\**.*.*"> <Visible>false</Visible> </Content>
itu tidak akan dipublikasikan.
Memperbarui
Karena Anda sudah menemukan wildcard akan diganti segera setelah Anda menyentuh folder di dalam solusi Anda karena proyek VS tidak dirancang untuk berisi konten yang berubah-ubah.
Jadi, Anda harus memastikan folder dan isinya tidak pernah diubah dari dalam VS - menambah atau menghapus file hanya dapat dilakukan pada sistem file ... yang Anda inginkan karena saya memahami pertanyaan Anda.
Akan lebih mudah jika folder dapat disembunyikan di VS tetapi saya tidak dapat menemukan cara untuk menyembunyikannya DAN mempublikasikannya.
Pendekatan lain yang tidak berhasil adalah memasukkan folder dengan
CreateItem
Tugas. Hal ini mengakibatkan konten folder dipublikasikan ke \ bin \ app.publish \ ... dan tidak dapat diyakinkan untuk menerbitkannya bersama dengan item konten di dalam .csproj jadi saya tidak menyajikannya dalam jawaban saya.sumber
<Content Include="Images\**\*.*" />
berhasil. Setelah Anda menambahkan lebih banyak gambar, .csproj diubah dan kembali ke daftar semua file dalam gambar / ... dan <Content Include = "Images * *. " /> Hilang.Bagi mereka yang mengalami masalah dalam menggunakan jawaban Chris , ini adalah solusi untuk Visual Studio 2012 dan yang lebih baru:
<Target Name="ContentsBeforeBuild" AfterTargets="BeforeBuild"> <ItemGroup> <Content Include="images\**" /> </ItemGroup> </Target>
Seperti yang dikatakan Chris dalam jawabannya - Visual Studio tidak akan menyentuh
<Target>
bagian ini , meskipun Anda secara manual mengutak-atik (menambahkan / menghapus file) dengan direktori target.Harap dicatat bahwa Anda harus menyertakan subdirektori tempat file-file tersebut berada (dalam kasus di atas, itu
images
). Visual Studio / MSBuild akan menempatkan file tersebut di direktori yang sama dalam struktur proyek. Jika Anda tidak menggunakan subdirektori, file akan ditempatkan di root struktur proyek.Untuk penjelasan singkat tentang wildcard:
**
Berarti semuanya secara rekursif (file, subdirektori, dan file di dalamnya)*.ext
akan menyertakan semua file dengan ekstensiext
di dalam direktori level teratas, tetapi tidak subdirektori*.ext
bisa*.png
,*.js
, dll Setiap ekstensi file akan bekerja**\*.ext
akan menyertakan semua file dengan ekstensiext
dari direktori level teratas dan semua subdirektori.Untuk penyelesaiannya, perlu diketahui bahwa ada perbedaan antara menggunakan
<Target>
dan tidak menggunakannya.Dengan
<Target>
pendekatan ini, Visual Studio tidak akan menampilkan file di dalam Solution Explorer.<Target Name="ContentsBeforeBuild" AfterTargets="BeforeBuild"> <ItemGroup> <Content Include="images\**" /> </ItemGroup> </Target>
<Target>
Pendekatan non- akan memerintahkan Visual Studio untuk menampilkan file dalam Solution Explorer. Kekurangannya adalah manipulasi direktori otomatis akan menyebabkan Visual Studio menimpa entri wildcard. Perlu juga dicatat bahwa pendekatan di bawah ini hanya akan memperbarui Penjelajah Solusi setelah membuka Solusi / Proyek di VS. Bahkan tombol toolbar "refresh" Solution Explorer tidak akan melakukannya.<ItemGroup> <Content Include="images\**" /> </ItemGroup>
sumber
BeforeBuild
acara? MSBuild harus terlebih dahulu membangun proyek dan binari sebelum dapat mempertimbangkan untuk menerbitkan... AfterTargets="BeforeBuild"
. Artinya, target khusus Anda harus dijalankan setelah BeforeBuild, tetapi tidak menentukan berapa banyak setelahnya. Padahal, kesalahan saya, dengan algoritme pengurutan target saat ini seharusnya ok: msdn.microsoft.com/en-us/library/ee216359.aspxAnda dapat menggunakan metode framework
System.IO.Directory.GetFile(string)
dan kelebihannya untuk menyertakan semua file secara rekursif.<ItemGroup> <Content Include="$([System.IO.Directory]::GetFiles('$(ProjectDir)Scripts\', '*.js', SearchOption.AllDirectories))" /> <Content Include="$([System.IO.Directory]::GetFiles('$(ProjectDir)Images\', '*.png', SearchOption.AllDirectories))" /> </ItemGroup>
sumber
Include="**\*.ext"
dengan wildcard.Saya telah menulis bagaimana saya bisa mendapatkan konten yang dibuat dengan skrip PowerShell kecil:
$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`" /> " }
Ini harus menghasilkan pernyataan include yang diperlukan pada prompt PowerShell
sumber
Anda dapat menambahkan file dengan link seperti ini, file tersebut dapat dicari, dapat dilihat, tetapi file tersebut tidak melakukan pembayaran jika Anda mencoba mengubahnya, juga studio visual membiarkan wildcard di tempatnya:
<ItemGroup> <Content Include="..\Database Schema\Views\*.sql"> <Link>Views\*.sql</Link> </Content> </ItemGroup>
Ini masuk ke dalam file .proj.
sumber
Tidak setahu saya; namun saran saya adalah menempelkannya ke dalam proyek karena ini akan menyertakannya secara default. Jadi, alih-alih menempelkannya ke direktori melalui Explorer, gunakan Visual Studio untuk menempelkan file ke dalam folder.
sumber
Saya menyadari bahwa solusi terbaik untuk ini adalah menambahkan file secara manual, satu per satu. Jika Anda memiliki ratusan seperti yang saya lakukan, itu hanya masalah beberapa jam. Lucunya di tahun 2016 dengan VS 2015 masalah serius ini masih belum terpecahkan. Ahh, betapa aku mencintai Xcode.
sumber