web-dev-qa-db-fra.com

Utilisation de msbuild pour exécuter un profil de publication du système de fichiers

J'ai un projet c # .Net 4.0 créé avec VS2010 et auquel on accède maintenant avec VS2012.

J'essaie de publier uniquement les fichiers nécessaires de ce site Web vers un emplacement de destination (C:\builds\MyProject [Files])

Ma structure de fichier: ./ProjectRoot/MyProject.csproj ./ProjectRoot/Properties/PublishProfiles/FileSystemDebug.pubxml

Je lance le suivant via MSBuild:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe ./ProjectRoot/MyProject.csproj/p: DeployOnBuild = true /p:PublishProfile =.

Voici le xml dans FileSystemDebug.pubxml

<Project ToolsVersion="4.0" xmlns="http://schemas.Microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <WebPublishMethod>FileSystem</WebPublishMethod>
    <LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
    <LastUsedPlatform>Any CPU</LastUsedPlatform>
    <SiteUrlToLaunchAfterPublish />
    <ExcludeApp_Data>False</ExcludeApp_Data>
    <publishUrl>C:\builds\MyProject\</publishUrl>
    <DeleteExistingFiles>True</DeleteExistingFiles>
  </PropertyGroup>
</Project>

Le comportement résultant est:

  • un fichier Zip est créé ici: ./ProjectRoot/obj/Debug/Package/MyProject.Zip
  • Rien n'est déployé vers<publishUrl>C:\builds\MyProject\</publishUrl>WTF
  • le fichier Zip créé est un petit-déjeuner cochon et plein de fichiers inutiles pour l'application.

Lorsque j'exécute ce profil de publication via Visual Studio, un dossier est créé dans * C:\builds\MyProject * et contient les artefacts exacts souhaités.

Comment puis-je obtenir ce résultat simple de msbuild?

74
P. Roe

FYI: J'ai eu le même problème avec Visual Studio 2015. Après plusieurs heures d’essais, je peux maintenant faire msbuild myproject.csproj /p:DeployOnBuild=true /p:PublishProfile=myprofile.

Je devais éditer mon fichier .csproj pour le faire fonctionner. Il contenait une ligne comme ceci:

<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" 
  Condition="false" />

J'ai changé cette ligne comme suit:

<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v14.0\WebApplications\Microsoft.WebApplication.targets" />

(J'ai changé 10.0 en 14.0, je ne suis pas sûr que cela soit nécessaire. Mais je devais absolument supprimer la partie condition.)

38
johanv

Trouvé la réponse ici: http://www.digitallycreated.net/Blog/59/locally-publishing-a-vs2010-asp.net-web-application-using-msbuild

Visual Studio 2010 propose une nouvelle nouvelle publication de projet d'application Web des fonctionnalités qui vous permettent de publier facilement votre projet d'application Web avec un clic d'un bouton. En coulisse, la transformation Web.config et la construction du paquet est faite par un script MSBuild massif qui est importé dans votre fichier de projet (à l'emplacement suivant: C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.targets) . Malheureusement, le script est extrêmement compliqué, désordonné et non documentés (autres que certains commentaires mal orthographiés et pour la plupart inutiles dans le fichier). Un grand organigramme de ce fichier et de certains la documentation sur la façon de s’y accrocher serait bien, mais semble être malheureusement (ou du moins je ne le trouve pas).

Malheureusement, cela signifie effectuer la publication via la ligne de commande est beaucoup plus opaque que nécessaire. J'ai été surpris par le manque de documentation dans ce domaine, car de nos jours beaucoup de magasins utilisent un serveur d'intégration continue et certains font même un déploiement automatisé (que les fonctionnalités de publication de VS2010 pourraient beaucoup aider), alors je aurait pensé que permettre cela (facilement!) aurait été un assez principale exigence pour la fonctionnalité.

Quoi qu’il en soit, après avoir fouillé dans le fichier Microsoft.Web.Publishing.targets limer pendant des heures et me cogner la tête contre le mur des essais et erreurs, J’ai réussi à comprendre comment Visual Studio semble s’acquitter de ses tâches magie un clic “Publier dans le système de fichiers” et “Construire le déploiement. «Forfait». Je vais entrer dans un peu de script MSBuild, donc Si vous n’êtes pas familier avec MSBuild, je vous suggère de consulter ce crash Bien sûr la page MSDN.

Publier dans un système de fichiers

La boîte de dialogue Publier vers un système de fichiers VS2010 Publier vers un système de fichiers prenait Il me faut un peu de temps, car je m'attendais à une utilisation judicieuse de MSBuild se produire. Au lieu de cela, VS2010 fait quelque chose d'assez bizarre: il appelle sur MSBuild pour effectuer une sorte de demi-déploiement qui prépare le Web les fichiers de l'application dans le dossier obj de votre projet, alors il semble faire un manuel copie de ces fichiers (en dehors de MSBuild) dans votre publication cible dossier. C’est vraiment un comportement dangereux parce que MSBuild est conçu pour copier des fichiers (et d’autres choses liées à la construction), cela aurait donc un sens si l'ensemble du processus n'était qu'une cible MSBuild appelée par VS2010 sur, pas une cible alors une copie manuelle.

Cela signifie que faire cela via MSBuild sur la ligne de commande n’est pas comme simple comme appeler votre fichier de projet avec une cible particulière et définir des propriétés. Vous devrez faire ce que VS2010 devrait faire done: créez vous-même une cible qui effectue le demi-déploiement puis copie les résultats dans le dossier cible. Pour éditer votre fichier de projet, Faites un clic droit sur le projet dans VS2010 et cliquez sur Décharger le projet, puis sur Cliquez à nouveau avec le bouton droit de la souris et cliquez sur Modifier. Faites défiler jusqu'à trouver le Importer un élément qui importe les cibles de l'application Web (Microsoft.WebApplication.targets; ce fichier lui-même importe le fichier Microsoft.Web.Publishing.targets mentionné précédemment). Sous cette ligne, nous allons ajouter notre nouvelle cible, appelée PublishToFileSystem:

<Target Name="PublishToFileSystem"
        DependsOnTargets="PipelinePreDeployCopyAllFilesToOneFolder">
    <Error Condition="'$(PublishDestination)'==''"
           Text="The PublishDestination property must be set to the intended publishing destination." />
    <MakeDir Condition="!Exists($(PublishDestination))"
             Directories="$(PublishDestination)" />

    <ItemGroup>
        <PublishFiles Include="$(_PackageTempDir)\**\*.*" />
    </ItemGroup>

    <Copy SourceFiles="@(PublishFiles)"
          DestinationFiles="@(PublishFiles->'$(PublishDestination)\%(RecursiveDir)%(Filename)%(Extension)')"
          SkipUnchangedFiles="True" />
</Target>

Cette cible dépend du Cible PipelinePreDeployCopyAllFilesToOneFolder, qui est ce que VS2010 appelle avant de faire sa copie manuelle. Certains creusent dans Microsoft.Web.Publishing.targets montre que l'appel de cette cible provoque les fichiers de projet à placer dans le répertoire spécifié par le fichier propriété _PackageTempDir.

La première tâche que nous appelons dans notre cible est la tâche d'erreur, sur laquelle nous avons placé une condition garantissant que la tâche n’est exécutée que si la propriété PublishDestination n’a pas été définie. Cela va vous attraper et une erreur sur la construction au cas où vous auriez oublié de spécifier le Propriété PublishDestination. Nous appelons ensuite la tâche MakeDir pour créer ce répertoire PublishDestination s’il n’existe pas déjà.

Nous définissons ensuite un élément appelé PublishFiles qui représente tout le fichiers trouvés dans le dossier _PackageTempDir. La tâche de copie est alors appelé qui copie tous ces fichiers dans le dossier Destination de publication . L'attribut DestinationFiles sur l'élément Copy est un peu complexe; il effectue une transformation des éléments et convertit leurs chemins en nouveaux chemins enracinés dans le dossier PublishDestination (consultez la section Métadonnées connues pour les éléments connus pour savoir ce que signifient ces% ()).

Pour appeler cette cible à partir de la ligne de commande, nous pouvons maintenant effectuer simplement cette commande (en modifiant évidemment le nom du fichier du projet et les propriétés selon vous):

msbuild Website.csproj "/p:Platform=AnyCPU;Configuration=Release;PublishDestination=F:\Temp\Publish" /t:PublishToFileSystem
39
P. Roe

J'avais toujours des problèmes après avoir essayé toutes les réponses ci-dessus (j'utilise Visual Studio 2013). Rien n'a été copié dans le dossier de publication.

Le problème était que si j'exécutais MSBuild avec un projet individuel plutôt qu'une solution, je devais mettre un paramètre supplémentaire spécifiant la version de Visual Studio:

/p:VisualStudioVersion=12.0

12.0 est pour VS2013, remplacez-le par la version que vous utilisez. Une fois que j'ai ajouté ce paramètre, cela a juste fonctionné.

La ligne de commande complète ressemble à ceci:

MSBuild C:\PathToMyProject\MyProject.csproj /p:DeployOnBuild=true /p:PublishProfile=MyPublishProfile /p:VisualStudioVersion=12.0

Je l'ai trouvé ici:

http://www.asp.net/mvc/overview/deployment/visual-studio-web-deployment/command-line-deployment

Ils déclarent:

Si vous spécifiez un projet individuel au lieu d'une solution, vous devez ajouter un paramètre spécifiant la version de Visual Studio.

18
felix-b

Il me semble que votre profil de publication n’est pas utilisé et que vous effectuez un conditionnement par défaut. Les cibles Microsoft Web Publish font tout ce que vous faites ci-dessus, elles sélectionnent les bonnes cibles en fonction de la configuration.

La mienne ne fonctionnait pas à l'étape TeamCity MSBuild, mais j'avais spécifié un chemin explicite vers le profil. Il vous suffisait de l'appeler par son nom, sans le. Il sera trouvé aussi longtemps que dans le dossier standard, qui est le vôtre.

Exemple:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe ./ProjectRoot/MyProject.csproj /p:DeployOnBuild=true /p:PublishProfile=FileSystemDebug

Notez que cette opération a été effectuée à l'aide des versions Visual Studio 2012 des cibles de publication Web Web, situées normalement dans l'emplacement "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\Web". Recherchez dans le dossier de déploiement les cibles de types de déploiement spécifiques utilisées

11
GregS

FYI: Même problème avec l'exécution sur un serveur de compilation (Jenkins avec msbuild 15 installé, piloté par VS 2017 sur un projet Web .NET Core 2.1).

Dans mon cas, c’est l’utilisation de la cible "publier" avec msbuild qui a ignoré le profil. 

Donc, ma commande msbuild a commencé avec:

msbuild /t:restore;build;publish

Cela a correctement déclenché le processus de publication, mais aucune combinaison ou variation de "/ p: PublishProfile = FolderProfile" n'a jamais permis de sélectionner le profil que je voulais utiliser ("FolderProfile").

Quand j'ai arrêté d'utiliser la cible de publication:

msbuild /t:restore;build /p:DeployOnBuild=true /p:PublishProfile=FolderProfile

(Bêtement) je pensais que cela ne ferait aucune différence, mais dès que j'ai utilisé le commutateur DeployOnBuild, il a correctement saisi le profil.

1
From Orbonia

En fait, j'ai fusionné toutes vos réponses à ma propre solution pour résoudre le problème ci-dessus:

  1. Je crée le fichier pubxml selon mes besoins
  2. Ensuite, je copie tous les paramètres du fichier pubxml vers ma propre liste de paramètres "/ p: foo = bar" pour msbuild.exe.
  3. Je jette le fichier pubxml

Le résultat est comme ça:

msbuild /t:restore /t:build /p:WebPublishMethod=FileSystem /p:publishUrl=C:\builds\MyProject\ /p:DeleteExistingFiles=True /p:LastUsedPlatform="Any CPU" /p:Configuration=Release

1
Rainer

Commencez par vérifier la version Visual Studio du PC développeur capable de publier la solution (projet). comme indiqué pour VS 2013

 /p:VisualStudioVersion=12.0

ajoutez la ligne de commande ci-dessus pour spécifier le type de version de Visual Studio qui doit générer le projet. En tant que réponses précédentes, cela peut se produire lorsque nous essayons de publier un seul projet et non la solution complète.

0
shammakalubo