Comment inclure des fichiers supplémentaires à l'aide des packages de déploiement Web VS2010?

125

Je teste la nouvelle fonctionnalité de packaging Web dans Visual Studio 2010 et suis tombé sur une situation dans laquelle j'utilise un événement de pré-construction pour copier les fichiers .dll requis dans mon dossier bin sur lequel mon application s'appuie pour les appels d'API. Ils ne peuvent pas être inclus en tant que référence car ils ne sont pas des DLL COM pouvant être utilisées avec l'interopérabilité.

Lorsque je crée mon package de déploiement, ces fichiers sont exclus lorsque je choisis l'option permettant d'inclure uniquement les fichiers requis pour exécuter l'application. Existe-t-il un moyen de configurer les paramètres de déploiement pour inclure ces fichiers? Je n'ai pas eu la chance de trouver une bonne documentation à ce sujet.

Jason
la source

Réponses:

176

Excellente question. Je viens de publier une entrée de blog très détaillée à ce sujet à Web Deployment Tool (MSDeploy): Build Package comprenant des fichiers supplémentaires ou excluant des fichiers spécifiques .

Voici le synopsis. Après avoir inclus des fichiers, je montre également comment exclure des fichiers.

Y compris des fichiers supplémentaires

L'inclusion de fichiers supplémentaires dans le package est un peu plus difficile mais toujours pas grave si vous êtes à l'aise avec MSBuild, et si vous ne l'êtes pas, lisez ceci. Pour ce faire, nous devons nous connecter à la partie du processus qui collecte les fichiers pour l'empaquetage. La cible que nous devons étendre est appelée CopyAllFilesToSingleFolder. Cette cible a une propriété de dépendance, PipelinePreDeployCopyAllFilesToOneFolderDependsOn, dans laquelle nous pouvons puiser et injecter notre propre cible. Nous allons donc créer une cible nommée CustomCollectFiles et l'injecter dans le processus. Nous y parvenons avec ce qui suit (rappelez-vous après la déclaration d'importation).

<PropertyGroup>
  <CopyAllFilesToSingleFolderForPackageDependsOn>
    CustomCollectFiles;
    $(CopyAllFilesToSingleFolderForPackageDependsOn);
  </CopyAllFilesToSingleFolderForPackageDependsOn>

  <CopyAllFilesToSingleFolderForMsdeployDependsOn>
    CustomCollectFiles;
    $(CopyAllFilesToSingleFolderForMsdeployDependsOn);
  </CopyAllFilesToSingleFolderForMsdeployDependsOn>
</PropertyGroup>

Cela ajoutera notre cible au processus, nous devons maintenant définir la cible elle-même. Supposons que vous ayez un dossier nommé Extra Files qui se trouve 1 niveau au-dessus de votre projet Web. Vous souhaitez inclure tous ces fichiers. Voici la cible CustomCollectFiles et nous en discuterons après.

<Target Name="CustomCollectFiles">
  <ItemGroup>
    <_CustomFiles Include="..\Extra Files\**\*" />

    <FilesForPackagingFromProject  Include="%(_CustomFiles.Identity)">
      <DestinationRelativePath>Extra Files\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
    </FilesForPackagingFromProject>
  </ItemGroup>
</Target>

Ici, j'ai créé l'élément _CustomFiles et dans l'attribut Inclure, je lui ai dit de récupérer tous les fichiers de ce dossier et de tout dossier en dessous. Si, par hasard, vous devez exclure quelque chose de cette liste, ajoutez un Excludeattribut à _CustomFiles.

Ensuite, j'utilise cet élément pour remplir l'élément FilesForPackagingFromProject. C'est l'élément que MSDeploy utilise réellement pour ajouter des fichiers supplémentaires. Notez également que j'ai déclaré la valeur DestinationRelativePath des métadonnées. Cela déterminera le chemin relatif dans lequel il sera placé dans le package. J'ai utilisé l'instruction Extra Files% (RecursiveDir)% (Filename)% (Extension) ici. Ce que cela signifie, c'est de le placer au même emplacement relatif dans le package que sous le dossier Extra Files.

Exclure des fichiers

Si vous ouvrez le fichier de projet d'une application Web créée avec VS 2010 vers le bas de celui-ci, vous trouverez une ligne avec.

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

BTW, vous pouvez ouvrir le fichier de projet à l'intérieur de VS. Cliquez avec le bouton droit sur le projet Choisissez Décharger le projet. Cliquez ensuite avec le bouton droit sur le projet déchargé et sélectionnez Modifier le projet.

Cette déclaration comprendra tous les objectifs et tâches dont nous avons besoin. La plupart de nos personnalisations devraient être après cette importation, si vous n'êtes pas sûr de les mettre après! Donc, si vous avez des fichiers à exclure, il existe un nom d'élément, ExcludeFromPackageFiles, qui peut être utilisé pour le faire. Par exemple, disons que vous avez un fichier nommé Sample.Debug.xml qui est inclus dans votre application Web mais que vous souhaitez que ce fichier soit exclu des packages créés. Vous pouvez placer l'extrait ci-dessous après cette instruction d'importation.

<ItemGroup>
  <ExcludeFromPackageFiles Include="Sample.Debug.xml">
    <FromTarget>Project</FromTarget>
  </ExcludeFromPackageFiles>
</ItemGroup>

En déclarant remplir cet élément, les fichiers seront automatiquement exclus. Notez l'utilisation des FromTargetmétadonnées ici. Je n'entrerai pas dans cela ici, mais vous devriez savoir de toujours le préciser.

Sayed Ibrahim Hashimi
la source
3
Pourriez-vous étendre votre exemple afin d'inclure des résultats de projet supplémentaires dans la publication?
Anthony Serdyukov
7
J'ai installé VS2012 (RC), et pour moi, il y avait une propriété DependencyProperty différente. Pour prendre en charge les équipes mixtes (et notre serveur de construction), j'avais la configuration originale CopyAllFilesToSingleFolderForPackageDependsOn et un doublon à l'aide de la DependencyProperty CopyAllFilesToSingleFolderForMsdeployDependsOn
Emil Lerch
2
C'est merveilleux. Utilisation de ceci pour déployer certaines informations de version stockées dans un fichier txt.
lamarant
5
Cela ne semble pas fonctionner pour moi. J'utilise VStudio 2013. :( La configuration de msbuild ci-dessus fonctionne-t-elle pour 2013?
irperez
8
@SayedIbrahimHashimi et co. ont créé une version beaucoup plus à jour de ce guide sur le site asp.net . Je recommande vivement ce lien, car c'était la différence entre le fait que je reste bloqué en modifiant le fichier csproj au lieu du fichier pubxml.
Adam Venezia
21

Une solution plus simple consiste à modifier le fichier csproj pour inclure la dll requise dans le dossier bin, puis à créer une cible beforebuild pour copier l'élément dans le dossier bin à partir du dossier de bibliothèque commun où nous stockons nos dll tierces. Étant donné que l'élément existe dans le fichier de solution, il est déployé par msbuild / msdeploy et rien de compliqué n'est nécessaire.

Balise utilisée pour inclure le fichier sans l'ajouter via VS (qui voudra généralement l'ajouter à votre VCS)

<Content Include="Bin\3rdPartyNative.dll" ><Visible>false</Visible></Content>

Voici la cible BeforeBuild qui a fonctionné pour moi:

<Target Name="BeforeBuild">
    <Message Text="Copy $(SolutionDir)Library\3rdPartyNative.dll to '$(TargetDir)'3rdPartyNative.dll" Importance="high" />
    <Copy SourceFiles="$(SolutionDir)Library\3rdPartyNative.dll" DestinationFiles="$(TargetDir)3rdPartyNative.dll" />
</Target>

Modifié pour inclure la suggestion de @ tuespetre de masquer l'entrée, supprimant ainsi l'inconvénient précédent d'un dossier bin visible. Non vérifié par moi.

toxaq
la source
3
"La simplicité est la sophistication ultime"
BornToCode
1
Cela fonctionne dans de nombreux cas, mais ne fonctionne pas si vous avez des fichiers qui doivent être inclus en dehors du dossier bin.
Nathan
5
@toxaq, il se peut que quelque chose me manque, mais le problème que j'ai rencontré était que j'avais en fait besoin des fichiers dans un emplacement du package de déploiement qui ne se trouvait pas dans le dossier bin. Alors oui, vous pouvez copier les fichiers de n'importe où dans le dossier bin, mais ils ne seront pas inclus au bon emplacement dans le package de déploiement dans ce scénario. Pour ce que cela vaut, la situation que j'ai rencontrée était avec le projet ClearScript.V8 - les .dll natives ne doivent pas apparaître dans le répertoire bin, mais doivent apparaître dans son parent - voir clearscript.codeplex.com/discussions/438696 pour la discussion .
Nathan
3
Je voterais dix fois de plus si je le pouvais. Cela devrait être la réponse acceptée. Je voudrais également ajouter que vous pouvez configurer <Visible>false</Visible>pour le masquer de l'Explorateur de solutions.
tuespetre
1
@Tohid merci, j'ai fait cette modification. Je n'ai pas de matériel MS à tester, donc je ne l'ai pas vérifié.
toxaq
7

Tout comme @toxaq, mais une solution encore plus simple consiste à:

Dans l'explorateur de solutions, ajoutez le fichier en tant que lien vers le dossier bibliothèque / références, puis définissez-le dans les propriétés pour qu'il soit copié dans la sortie de la construction.

Eglasius
la source
3
-1 cela suppose que le projet souhaite avoir une relation éditeur-temps explicite. Ne convient pas aux systèmes de type plug-in
MickyD
6

La mise en œuvre de Sayed n'a donc pas fonctionné pour moi. J'utilise VS2013 et j'utilise le package Web Deploy et je devais ajouter des DLL de plug-in d'un autre dossier dans la corbeille du package de déploiement. Voici comment j'ai réussi à le faire fonctionner (beaucoup plus facilement):

Au bas de votre fichier csproj ajoutez:

<Target Name="AdditionalFilesForPackage" AfterTargets="CopyAllFilesToSingleFolderForMsdeploy">
    <ItemGroup> 
        <Files Include="..\SomeOtherProject\bin\$(Configuration)\*.*"/>
    </ItemGroup>
    <Copy SourceFiles="@(Files)" DestinationFolder="$(_PackageTempDir)\bin\" />  
</Target>

Autres mentionnables dans le fichier csproj:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <DeployOnBuild>true</DeployOnBuild>
    <DeployTarget>Package</DeployTarget>
    <DeployIisAppPath>Default Web Site/MyWebsite</DeployIisAppPath>
    <DesktopBuildPackageLocation>..\output\Service\Service\Service.Release.zip</DesktopBuildPackageLocation>
    <FilesToIncludeForPublish>OnlyFilesToRunTheApp</FilesToIncludeForPublish>
    <ExcludeGeneratedDebugSymbol>true</ExcludeGeneratedDebugSymbol>
    <PublishDatabases>false</PublishDatabases>
</PropertyGroup>

<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v12.0\WebApplications\Microsoft.WebApplication.targets" />
K0D4
la source
Je vous remercie. J'utilise VS2015 et j'avais également besoin d'ajouter DLLS à partir d'un autre dossier bin de projet. Votre solution était la plus simple et fonctionnait parfaitement.
Rafael le
5

Voulait commenter pour souligner le commentaire d'Emil Lerch ci-dessus. Si vous avez installé un Kit de développement logiciel (SDK) Azure, recherchez un DependencyProperty différent.

Fondamentalement, vous devrez peut-être utiliser "CopyAllFilesToSingleFolderForMsdeployDependsOn" au lieu de "CopyAllFilesToSingleFolderForPackageDependsOn". Je ne suis pas vraiment un gars avancé de MsBuild et j'ai perdu des heures à m'arracher les cheveux à essayer de déterminer pourquoi mes cibles n'étaient pas appelées.

Voici un autre lien si cela ne fonctionne pas pour vous et que vous avez installé un SDK Azure: http://forums.iis.net/t/1190714.aspx

Paul Schroeder
la source
3

En complément de la réponse de Sayed, j'ai trouvé qu'une déclaration statique des éléments ExcludeFromPackageFiles dans mon projet n'était pas suffisante. J'avais besoin d'exclure certaines DLL qui n'étaient disponibles qu'après la compilation (modules Ninject spécifiques à Azure qui ne sont pas nécessaires lorsque je déploie sur IIS).

J'ai donc essayé de générer ma liste ExcludeFromPackageFiles en utilisant l'astuce CopyAllFilesToSingleFolderForPackageDependsOn Sayed publiée ci-dessus. Cependant, cela est trop tard car le processus de création de package a déjà supprimé les éléments ExcludeFromPackageFiles. J'ai donc utilisé la même technique, mais un peu plus tôt:

<PropertyGroup>
    <ExcludeFilesFromPackageDependsOn>
        $(ExcludeFilesFromPackageDependsOn);
        _ExcludeAzureDlls
    </ExcludeFilesFromPackageDependsOn>
</PropertyGroup>

<Target Name="_ExcludeAzureDlls">
    <ItemGroup>
        <FilesForPackagingFromProjectWithNoAzure Include="@(FilesForPackagingFromProject)"
                               Exclude="%(RootDir)%(Directory)*Azure*.dll" />
        <AzureFiles Include="@(FilesForPackagingFromProject)"
                    Exclude="@(FilesForPackagingFromProjectWithNoAzure)" />
        <ExcludeFromPackageFiles Include="@(AzureFiles)">
            <FromTarget>_ExcludeAzureEnvironmentDlls</FromTarget>
        </ExcludeFromPackageFiles>
    </ItemGroup>
</Target>

J'espère que cela aide quelqu'un ...

Peter McEvoy
la source
1

En outre, il est possible de définir le fichier comme Contenu | Copiez toujours

En outre, il est possible de définir le fichier comme Contenu |  Copiez toujours

Fabito
la source
1
Il semble que cela devrait être la meilleure réponse car c'est la plus simple et la plus évidente
J Miglietta