J'ajoute fréquemment beaucoup de fichiers de contenu (principalement des images et des js) à mon projet ASP.NET. J'utilise le système de publication VS et lors de la publication, les nouveaux fichiers ne sont pas publiés tant que je ne les ai pas inclus dans le projet. Je voudrais inclure automatiquement tous les fichiers dans le répertoire spécifié. Existe-t-il un moyen de spécifier quels répertoires doivent être automatiquement inclus dans le fichier csproj ou ailleurs?
86
Réponses:
Vieux fil, je sais, mais j'ai trouvé un moyen de faire cela que je n'arrête pas d'oublier, et dans ma recherche pour le retrouver une dernière fois, je suis tombé sur cette question. Le meilleur moyen que j'ai trouvé pour cela est d'utiliser la cible BeforeBuild dans le fichier .csproj.
<Target Name="BeforeBuild"> <ItemGroup> <Content Include="**\*.less" /> </ItemGroup> </Target>
VS 2010 ne touchera pas à cette section et garantit que vos fichiers sont inclus en tant que contenu à chaque fois que le projet est créé.
la source
**\*.less
?**\*.less
signifie inclure tous les fichiers * .less dans tous les répertoires. Dans MSBUILD, ** signifie `` tous les répertoires de manière récursive ''Vous pouvez simplement étendre le fichier .csproj de votre site Web. Ajoutez simplement votre dossier racine de contenu avec un caractère générique récursif:
... <ItemGroup> <!-- your normal project content --> <Content Include="Default.aspx" /> <!-- your static content you like to publish --> <Content Include="Images\**\*.*" /> </ItemGroup> ...
Cela rend ce dossier et tout le contenu ci-dessous visibles dans votre navigateur de solution.
Si vous essayez de masquer le dossier dans le navigateur de solution en spécifiant
<Content Include="Images\**.*.*"> <Visible>false</Visible> </Content>
il ne sera pas publié.
Mise à jour
Comme vous l'avez déjà découvert, le caractère générique sera remplacé dès que vous toucherez le dossier à l'intérieur de votre solution car les projets VS ne sont pas conçus pour contenir un contenu arbitraire.
Vous devrez donc vous assurer que le dossier et son contenu ne sont jamais modifiés à partir de VS - l'ajout ou la suppression de fichiers ne peut être fait que sur le système de fichiers ... c'est ce que vous vouliez après avoir compris votre question.
Ce serait plus facile si le dossier pouvait être caché dans VS mais je ne pouvais pas trouver un moyen de le cacher ET de le publier.
Une autre approche infructueuse consistait à inclure le dossier par une
CreateItem
tâche. Cela a abouti à la publication du contenu du dossier dans \ bin \ app.publish \ ... et je n'ai pas pu être convaincu de le publier avec les éléments de contenu à l'intérieur du .csproj, donc je ne l'ai pas présenté dans ma réponse.la source
<Content Include="Images\**\*.*" />
cela a fonctionné. Une fois que vous avez ajouté d'autres images, le .csproj est modifié et revient à la liste de tous les fichiers dans les images / ... et le <Content Include = "Images * *. " /> Est parti.Pour ceux qui rencontrent des problèmes avec la réponse de Chris, voici la solution pour Visual Studio 2012 et plus récent:
<Target Name="ContentsBeforeBuild" AfterTargets="BeforeBuild"> <ItemGroup> <Content Include="images\**" /> </ItemGroup> </Target>
Comme Chris l'a mentionné dans sa réponse - Visual Studio n'y touchera pas
<Target>
section, même si vous manipulez manuellement (ajout / suppression de fichiers) avec le répertoire cible.S'il vous plaît noter que vous devez inclure un sous - répertoire où se trouvent les fichiers (dans le cas ci - dessus, il est
images
). Visual Studio / MSBuild placera ces fichiers dans le même répertoire dans la structure du projet. Si vous n'utilisez pas de sous-répertoire, les fichiers seront placés à la racine de la structure du projet.Pour une explication rapide des caractères génériques:
**
signifie tout récursivement (fichiers, sous-répertoires et fichiers dans ceux-ci)*.ext
inclura tous les fichiers avec l'extensionext
dans le répertoire de niveau supérieur, mais pas les sous-répertoires*.ext
pourrait être*.png
,*.js
etc. Toute extension de fichier ne fonctionnera**\*.ext
inclura tous les fichiers avec l'extensionext
du répertoire de niveau supérieur et tous les sous-répertoires.Pour terminer, veuillez noter qu'il existe une différence entre l'utiliser
<Target>
et ne pas l'utiliser.Avec l'
<Target>
approche, Visual Studio n'affichera pas les fichiers dans l'Explorateur de solutions.<Target Name="ContentsBeforeBuild" AfterTargets="BeforeBuild"> <ItemGroup> <Content Include="images\**" /> </ItemGroup> </Target>
La non -
<Target>
approche va donner des instructions Visual Studio pour afficher les fichiers dans la solution Explorer. L'inconvénient de celui-ci est que toute manipulation des répertoires automatiques entraînera le remplacement de l'entrée générique par Visual Studio. Il convient également de noter que l'approche ci-dessous ne mettra à jour l'Explorateur de solutions qu'à l'ouverture de la solution / projet dans VS. Même le bouton "Actualiser" de la barre d'outils de l'Explorateur de solutions ne le fera pas.<ItemGroup> <Content Include="images\**" /> </ItemGroup>
la source
BeforeBuild
événement? MSBuild doit d'abord générer le projet et les binaires avant même d'envisager la publication... AfterTargets="BeforeBuild"
. Cela signifie que votre cible personnalisée doit s'exécuter après BeforeBuild, mais elle ne spécifie pas combien après. Cependant, mon erreur, selon l'algorithme de commande des cibles actuel, cela devrait être correct: msdn.microsoft.com/en-us/library/ee216359.aspxVous pouvez utiliser la
System.IO.Directory.GetFile(string)
méthode du framework et ses surcharges pour inclure récursivement tous les fichiers.<ItemGroup> <Content Include="$([System.IO.Directory]::GetFiles('$(ProjectDir)Scripts\', '*.js', SearchOption.AllDirectories))" /> <Content Include="$([System.IO.Directory]::GetFiles('$(ProjectDir)Images\', '*.png', SearchOption.AllDirectories))" /> </ItemGroup>
la source
Include="**\*.ext"
qu'avec les jokers.J'ai écrit comment j'ai pu obtenir le contenu créé avec un petit script 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`" /> " }
Cela devrait produire l'instruction include nécessaire à l'invite PowerShell
la source
Vous pouvez ajouter des fichiers avec des liens comme celui-ci, ils sont consultables, consultables, mais ils ne sont pas récupérés si vous essayez de les modifier.Visual studio laisse également les caractères génériques en place:
<ItemGroup> <Content Include="..\Database Schema\Views\*.sql"> <Link>Views\*.sql</Link> </Content> </ItemGroup>
Cela va dans le fichier .proj.
la source
Pas à ma connaissance; cependant ma suggestion est de les coller dans le projet car cela les inclura par défaut. Ainsi, au lieu de les coller dans le répertoire via l'Explorateur, utilisez Visual Studio pour coller les fichiers dans les dossiers.
la source
J'ai réalisé que la meilleure solution pour cela était d'ajouter manuellement des fichiers, un par un. Si vous en avez des centaines comme moi, ce n'était qu'une question de quelques heures. C'est drôle que même en 2016 avec VS 2015, ce grave problème ne soit toujours pas résolu. Ahh, comme j'aime Xcode.
la source