Como você inclui arquivos adicionais usando pacotes de implantação na web do VS2010?

125

Estou testando usando a nova funcionalidade de empacotamento da web no visual studio 2010 e me deparei com uma situação em que eu uso um evento de pré-compilação para copiar as DLLs necessárias na minha pasta bin na qual meu aplicativo depende para chamadas de API. Eles não podem ser incluídos como referência, pois não são dlls COM que podem ser usadas com interoperabilidade.

Quando crio meu pacote de implantação, esses arquivos são excluídos quando escolho a opção de incluir apenas os arquivos necessários para executar o aplicativo. Existe uma maneira de definir as configurações de implantação para incluir esses arquivos? Não tive sorte em encontrar uma boa documentação sobre isso.

Jason
fonte

Respostas:

176

Ótima pergunta. Acabei de publicar uma entrada de blog muito detalhada sobre isso na Web Deployment Tool (MSDeploy): Build Package incluindo arquivos extras ou excluindo arquivos específicos .

Aqui está a sinopse. Depois de incluir os arquivos, mostro como excluir os arquivos também.

Incluindo arquivos extras

Incluir arquivos extras no pacote é um pouco mais difícil, mas ainda não é demais, se você se sentir confortável com o MSBuild e, se não estiver, leia isso. Para fazer isso, precisamos nos conectar à parte do processo que coleta os arquivos para empacotamento. O destino que precisamos estender é chamado CopyAllFilesToSingleFolder. Esse destino possui uma propriedade de dependência, PipelinePreDeployCopyAllFilesToOneFolderDependsOn, na qual podemos acessar e injetar nosso próprio destino. Portanto, criaremos um destino chamado CustomCollectFiles e o injetaremos no processo. Conseguimos isso com o seguinte (lembre-se após a declaração de importação).

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

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

Isso adicionará nosso objetivo ao processo, agora precisamos definir o próprio objetivo. Vamos supor que você tenha uma pasta chamada Arquivos Extra que fica 1 nível acima do seu projeto da web. Você deseja incluir todos esses arquivos. Aqui está o destino CustomCollectFiles e discutiremos depois disso.

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

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

Aqui, o que eu fiz foi criar o item _CustomFiles e, no atributo Include, disse para ele pegar todos os arquivos nessa pasta e qualquer pasta abaixo dele. Se por acaso você precisar excluir algo dessa lista, adicione um Excludeatributo a _CustomFiles.

Então eu uso esse item para preencher o item FilesForPackagingFromProject. Este é o item que o MSDeploy realmente usa para adicionar arquivos extras. Observe também que declarei o valor de destino de metadados DestinationRelativePath. Isso determinará o caminho relativo que será colocado no pacote. Usei a instrução Extra Files% (RecursiveDir)% (Filename)% (Extension) aqui. O que está dizendo é colocá-lo no mesmo local relativo no pacote, na pasta Arquivos Extra.

Excluindo arquivos

Se você abrir o arquivo do projeto de um aplicativo Web criado com o VS 2010 na parte inferior, encontrará uma linha com.

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

BTW, você pode abrir o arquivo do projeto dentro do VS. Clique com o botão direito do mouse no projeto e escolha Unload Project. Em seguida, clique com o botão direito do mouse no projeto descarregado e selecione Editar Projeto.

Esta declaração incluirá todos os objetivos e tarefas que precisamos. A maioria de nossas personalizações deve ser posterior a essa importação, se você não tiver certeza se será depois! Portanto, se você tiver arquivos para excluir, existe um nome de item, ExcludeFromPackageFiles, que pode ser usado para fazer isso. Por exemplo, digamos que você tenha o arquivo Sample.Debug.xml, incluído no seu aplicativo da Web, mas deseje que esse arquivo seja excluído dos pacotes criados. Você pode colocar o snippet abaixo após a declaração de importação.

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

Ao declarar preencher esse item, os arquivos serão automaticamente excluídos. Observe o uso dos FromTargetmetadados aqui. Não vou abordar isso aqui, mas você deve saber sempre especificar isso.

Sayed Ibrahim Hashimi
fonte
3
Você poderia estender seu exemplo para incluir saída de projeto adicional na publicação?
Anthony Serdyukov 21/03
7
Eu tenho o VS2012 (RC) instalado e, para mim, havia um DependencyProperty diferente. Para apoiar equipes mistas (e nosso servidor de compilação), tive a configuração CopyAllFilesToSingleFolderForPackageDependsOn originais e uma cópia usando o DependencyProperty CopyAllFilesToSingleFolderForMsdeployDependsOn
Emil Lerch
2
Isso é maravilhoso. Use isso para implantar algumas informações de versão armazenadas em um arquivo txt.
Lamarant 01/11
5
Isso não parece funcionar para mim. Estou usando o VStudio 2013. :( A instalação do msbuild acima funciona em 2013?
irperez
8
@SayedIbrahimHashimi and co. criamos uma versão muito mais atualizada deste guia no site asp.net . Eu recomendo esse link, pois essa foi a diferença entre eu ficar preso ao modificar o arquivo csproj em vez do arquivo pubxml.
23315 Adam Adamia #
21

Uma solução mais simples é editar o arquivo csproj para incluir a dll necessária na pasta bin e, em seguida, criar um destino beforebuild para copiar o item na pasta bin da pasta da biblioteca comum, onde armazenamos nossas DLLs de terceiros. Como o item existe no arquivo de solução, ele é implantado pelo msbuild / msdeploy e não é necessário nada complicado.

Tag usado para incluir o arquivo sem adicionar através do VS (que geralmente é necessário adicioná-lo ao seu VCS)

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

Este é o destino BeforeBuild que funcionou para mim:

<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 a sugestão de @ tuespetre de ocultar a entrada, removendo a desvantagem anterior de uma pasta bin visível. Não verificado por mim.

toxaq
fonte
3
"simplicidade é a sofisticação final"
BornToCode
1
Isso funciona em muitos casos, mas não funciona se você tiver arquivos que precisam ser incluídos fora da pasta bin.
Nathan
5
@toxaq, poderia estar faltando alguma coisa, mas o problema que encontrei foi que eu realmente precisava dos arquivos em um local no pacote de implantação que não estava na pasta bin. Portanto, sim, você pode copiar os arquivos de qualquer lugar para a pasta bin, mas eles não serão incluídos no local certo no pacote de implantação nesse cenário. Quanto a seu valor, a situação em que me deparei foi com o projeto ClearScript.V8 - as .dlls nativas não devem aparecer no diretório bin, mas devem aparecer em seu pai - consulte clearscript.codeplex.com/discussions/438696 para obter a discussão .
19413 Nathan
3
Eu votaria mais dez vezes, se pudesse. Essa deve ser a resposta aceita. Gostaria também de acrescentar que você pode configurá <Visible>false</Visible>-lo para ocultá-lo no Solution Explorer.
tuespetre
1
@ Oh, obrigado, fizeram essa edição. Não tem nenhum material MS para testar, por isso não o verifiquei.
toxaq
7

Assim como @toxaq, mas uma solução ainda mais simples é:

No gerenciador de soluções, adicione o arquivo como um link à pasta library / reference e, em seguida, nas propriedades, defina-o para ser copiado na saída da construção.

eglasius
fonte
3
-1 assume que o projeto deseja ter um relacionamento explícito entre o vinculador e o tempo. Não é adequado para plug-in sistemas do tipo
MickyD
6

A implementação de Sayed não funcionou para mim. Estou usando o VS2013 e usando o pacote Web Deploy e precisava adicionar algumas DLLs de plug-in de outra pasta na lixeira do pacote de implantação. Veja como eu consegui fazê-lo funcionar (muito mais fácil):

Na parte inferior do seu arquivo csproj, adicione:

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

Outras referências no arquivo 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
fonte
Obrigado. Estou usando o VS2015 e também precisava adicionar DLLS de outra pasta bin do projeto. Sua solução foi a mais fácil e funcionou perfeitamente.
Rafael Rafael
5

Queria comentar para enfatizar o comentário de Emil Lerch acima. Se você instalou um SDK do Azure, procure um DependencyProperty diferente.

Basicamente, você pode precisar usar "CopyAllFilesToSingleFolderForMsdeployDependsOn em vez de" CopyAllFilesToSingleFolderForPackageDependsOn ". Eu não sou realmente um cara avançado do MsBuild e perdi horas puxando meu cabelo tentando determinar por que meus destinos não estavam sendo chamados.

Aqui está outro link, se isso não funcionar para você e você instalou um SDK do Azure: http://forums.iis.net/t/1190714.aspx

Paul Schroeder
fonte
3

Como um adendo à resposta de Sayed, descobri que uma declaração estática dos itens ExcludeFromPackageFiles no meu projeto não era suficiente. Eu precisava excluir determinadas DLLs que só estavam disponíveis após compilação (módulos Ninject específicos do Azure que não são necessários quando eu implanto no IIS).

Então, tentei ligar a geração da minha lista ExcludeFromPackageFiles usando o truque CopyAllFilesToSingleFolderForPackageDependsOn Sayed postado acima. No entanto, é tarde demais, pois o processo de empacotamento já removeu os itens ExcludeFromPackageFiles. Então, eu usei a mesma técnica, mas um pouco 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 ajude alguém ...

Peter McEvoy
fonte
1

Além disso, é possível definir o arquivo como Conteúdo | Copie sempre

Além disso, é possível definir o arquivo como Conteúdo |  Copie sempre

Fabito
fonte
1
Parece que esta deve ser a resposta principal, pois é a mais fácil e mais óbvia
J Miglietta 25/03