¿Cómo se incluyen archivos adicionales con los paquetes de implementación web VS2010?

125

Estoy probando el uso de la nueva funcionalidad de empaquetado web en Visual Studio 2010 y me encontré con una situación en la que uso un evento previo a la compilación para copiar los archivos .dll requeridos en mi carpeta bin en la que mi aplicación depende para las llamadas API. No se pueden incluir como referencia ya que no son archivos COM COM que se pueden usar con interoperabilidad.

Cuando construyo mi paquete de implementación, esos archivos se excluyen cuando elijo la opción de incluir solo los archivos necesarios para ejecutar la aplicación. ¿Hay alguna forma de configurar los ajustes de implementación para incluir estos archivos? No he tenido suerte de encontrar buena documentación sobre esto.

Jason
fuente

Respuestas:

176

Gran pregunta Acabo de publicar una entrada de blog muy detallada sobre esto en la Herramienta de implementación web (MSDeploy): paquete de compilación que incluye archivos adicionales o excluye archivos específicos .

Aquí está la sinopsis. Después de incluir archivos, también muestro cómo excluir archivos.

Incluyendo archivos adicionales

Incluir archivos adicionales en el paquete es un poco más difícil, pero aún no es un patudo si te sientes cómodo con MSBuild, y si no lo estás, lee esto. Para hacer esto, necesitamos conectarnos a la parte del proceso que recopila los archivos para empaquetarlos. El objetivo que necesitamos extender se llama CopyAllFilesToSingleFolder. Este objetivo tiene una propiedad de dependencia, PipelinePreDeployCopyAllFilesToOneFolderDependsOn, que podemos aprovechar e inyectar nuestro propio objetivo. Entonces crearemos un objetivo llamado CustomCollectFiles e inyectaremos eso en el proceso. Logramos esto con lo siguiente (recuerde después de la declaración de importación).

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

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

Esto agregará nuestro objetivo al proceso, ahora necesitamos definir el objetivo en sí. Supongamos que tiene una carpeta llamada Archivos adicionales que se encuentra 1 nivel por encima de su proyecto web. Desea incluir todos esos archivos. Aquí está el objetivo CustomCollectFiles y discutimos después de eso.

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

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

Aquí lo que hice fue crear el elemento _CustomFiles y en el atributo Incluir le dije que recogiera todos los archivos en esa carpeta y cualquier carpeta debajo de él. Si por casualidad necesita excluir algo de esa lista, agregue un Excludeatributo a _CustomFiles.

Luego uso este elemento para llenar el elemento FilesForPackagingFromProject. Este es el elemento que MSDeploy realmente usa para agregar archivos adicionales. Observe también que he declarado el valor de metadatos DestinationRelativePath. Esto determinará la ruta relativa que se colocará en el paquete. Usé la declaración Archivos adicionales% (RecursiveDir)% (Nombre de archivo)% (Extensión) aquí. Lo que está diciendo es colocarlo en la misma ubicación relativa en el paquete que está debajo de la carpeta Archivos adicionales.

Excluyendo archivos

Si abre el archivo de proyecto de una aplicación web creada con VS 2010 en la parte inferior, encontrará una línea con.

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

Por cierto, puede abrir el archivo del proyecto dentro de VS. Haga clic derecho en el proyecto, seleccione Descargar proyecto. Luego haga clic derecho en el proyecto descargado y seleccione Editar proyecto.

Esta declaración incluirá todos los objetivos y tareas que necesitamos. La mayoría de nuestras personalizaciones deben realizarse después de esa importación, si no está seguro, ¡ponga después! Entonces, si tiene que excluir archivos, hay un nombre de elemento, ExcludeFromPackageFiles, que puede usarse para hacerlo. Por ejemplo, supongamos que tiene un archivo llamado Sample.Debug.xml que se incluye en su aplicación web pero desea que ese archivo se excluya de los paquetes creados. Puede colocar el fragmento a continuación después de esa declaración de importación.

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

Al declarar completar este elemento, los archivos se excluirán automáticamente. Tenga en cuenta el uso de los FromTargetmetadatos aquí. No voy a entrar en eso aquí, pero debes saber especificar siempre eso.

Sayed Ibrahim Hashimi
fuente
3
¿Podría extender su ejemplo para incluir resultados de proyectos adicionales en la publicación?
Anthony Serdyukov
77
Tengo VS2012 (RC) instalado, y para mí había una DependencyProperty diferente. Para admitir equipos mixtos (y nuestro servidor de compilación), tuve la configuración original CopyAllFilesToSingleFolderForPackageDependsOn y un duplicado usando DependencyProperty CopyAllFilesToSingleFolderForMsdeployDependsOn
Emil Lerch el
2
Esto es maravilloso. Usando esto para desplegar alguna información de versión almacenada en un archivo txt.
lamarant
55
Esto no parece funcionar para mí. Estoy usando VStudio 2013. :( ¿La configuración de msbuild anterior funciona para 2013?
irperez
8
@SayedIbrahimHashimi y compañía. he creado una versión mucho más actualizada de esta guía en el sitio web asp.net . Recomiendo encarecidamente ese enlace, ya que esa fue la diferencia entre que me quede atascado modificando el archivo csproj en lugar del archivo pubxml.
Adam Venezia
21

Una solución más simple es editar el archivo csproj para incluir el dll requerido en la carpeta bin y luego crear un objetivo antes de construir para copiar el elemento en la carpeta bin desde la carpeta de biblioteca común donde almacenamos nuestros archivos dlls de terceros. Debido a que el elemento existe en el archivo de solución, msbuild / msdeploy lo implementa y no se necesita nada complicado.

La etiqueta solía incluir el archivo sin agregar a través de VS (que generalmente querrá agregarlo a su VCS)

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

Este es el objetivo BeforeBuild que funcionó para mí:

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

Editado para incluir la sugerencia de @ tuespetre para ocultar la entrada, eliminando así la desventaja anterior de una carpeta bin visible. No verificado por mí.

toxaq
fuente
3
"La simplicidad es la máxima sofisticación"
BornToCode
1
Esto funciona en muchos casos, pero no funciona si tiene archivos que deben incluirse fuera de la carpeta bin.
Nathan
55
@toxaq, me podría faltar algo, pero el problema que encontré fue que realmente necesitaba los archivos en una ubicación en el paquete de implementación que no estaba en la carpeta bin. Entonces, sí, puede copiar los archivos desde cualquier lugar a la carpeta bin, pero no se incluirán en la ubicación correcta en el paquete de implementación en ese escenario. Para lo que vale, la situación con la que me encontré fue con el proyecto ClearScript.V8: los .dlls nativos no deben aparecer en el directorio bin, pero deben aparecer en su padre, consulte clearscript.codeplex.com/discussions/438696 para la discusión .
Nathan
3
Votaría diez veces más si pudiera. Esta debería ser la respuesta aceptada. También me gustaría agregar que puede configurarlo <Visible>false</Visible>para ocultarlo del Explorador de soluciones.
martes
1
@Tohid gracias, he hecho esa edición. No tengo nada de MS para probar, así que no lo he verificado.
toxaq
7

Al igual que @toxaq, pero una solución aún más simple es:

En el explorador de soluciones, agregue el archivo como un enlace a la carpeta de la biblioteca / referencias, y luego, en las propiedades, configúrelo para que se copie en la salida de la compilación.

eglasius
fuente
3
-1 esto supone que el proyecto desea tener una relación explícita de enlazador-tiempo. No es adecuado para sistemas de tipo
enchufable
6

Entonces la implementación de Sayed no funcionó para mí. Estoy usando VS2013 y estoy usando el paquete Web Deploy y necesitaba agregar algunas DLL de plugin de otra carpeta al contenedor del paquete de implementación. Así es como logré hacerlo funcionar (mucho más fácil):

En la parte inferior de su archivo csproj agregue:

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

Otros mencionables en el archivo 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
fuente
Gracias. Estoy usando VS2015 y también necesitaba agregar DLLS desde otra carpeta bin del proyecto. Su solución fue la más fácil y funcionó a la perfección.
Rafael
5

Quería comentar para enfatizar el comentario de Emil Lerch arriba. Si ha instalado un SDK de Azure, busque una propiedad de dependencia diferente.

Básicamente, es posible que deba usar "CopyAllFilesToSingleFolderForMsdeployDependsOn en lugar de" CopyAllFilesToSingleFolderForPackageDependsOn ". No soy realmente un tipo avanzado de MsBuild y perdí muchas horas tratando de determinar por qué no se llamaba a mis objetivos.

Aquí hay otro enlace si esto no funciona para usted y ha instalado un SDK de Azure: http://forums.iis.net/t/1190714.aspx

Paul Schroeder
fuente
3

Como anexo a la respuesta de Sayed, descubrí que una declaración estática de elementos ExcludeFromPackageFiles dentro de mi proyecto no era suficiente. Necesitaba excluir ciertas DLL que solo estaban disponibles después de la compilación (módulos Ninject específicos de Azure que no son necesarios cuando implemento en IIS).

Así que intenté enganchar la generación de mi lista ExcludeFromPackageFiles usando el truco CopyAllFilesToSingleFolderForPackageDependsOn Sayed publicado anteriormente. Sin embargo, esto es demasiado tarde ya que el proceso de empaquetado ya eliminó los elementos ExcludeFromPackageFiles. Entonces, utilicé la misma técnica, pero un poco antes:

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

Espero que ayude a alguien ...

Peter McEvoy
fuente
1

Además, es posible configurar el archivo como Contenido | Copia siempre

Además, es posible configurar el archivo como Contenido |  Copia siempre

Fabito
fuente
1
Parece que esta debería ser la respuesta principal, ya que es la más fácil y obvia
J Miglietta