Partilhar via


Implantação de arquivo único

A agregação de todos os arquivos dependentes do aplicativo em um único binário fornece ao desenvolvedor de aplicativos a opção atraente de implantar e distribuir o aplicativo como um único arquivo. A implantação de arquivo único está disponível tanto para o modelo de implantação dependente da estrutura quanto para aplicativos autônomos.

O tamanho do arquivo único em um aplicativo autônomo é grande, pois inclui o tempo de execução e as bibliotecas de estrutura. No .NET 6, você pode publicar cortado para reduzir o tamanho total de aplicativos compatíveis com corte. A opção de implantação de arquivo único pode ser combinada com as opções de publicação ReadyToRun e Trim .

Importante

Para executar um aplicativo de arquivo único no Windows 7, você deve usar o .NET Runtime 6.0.3 ou posterior.

Arquivo de projeto de exemplo

Aqui está um arquivo de projeto de exemplo que especifica a publicação de arquivo único:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <PublishSingleFile>true</PublishSingleFile>
    <SelfContained>true</SelfContained>
    <RuntimeIdentifier>win-x64</RuntimeIdentifier>
  </PropertyGroup>

</Project>

Estas propriedades têm as seguintes funções:

  • PublishSingleFile. Permite a publicação de um único arquivo. Também permite avisos de arquivo único durante dotnet buildo .
  • SelfContained. Determina se o aplicativo é autônomo ou dependente da estrutura.
  • RuntimeIdentifier. Especifica o sistema operacional e o tipo de CPU que você está segmentando. Também define <SelfContained>true</SelfContained> por padrão.

Os aplicativos de arquivo único são sempre específicos do sistema operacional e da arquitetura. Você precisa publicar para cada configuração, como Linux x64, Linux Arm64, Windows x64 e assim por diante.

Os arquivos de configuração de tempo de execução, como *.runtimeconfig.json e *.deps.json, são incluídos no arquivo único. Se for necessário um arquivo de configuração extra, você pode colocá-lo ao lado do arquivo único.

Publicar um aplicativo de arquivo único

Publique um aplicativo de arquivo único usando o comando dotnet publishing .

  1. Adicione <PublishSingleFile>true</PublishSingleFile> ao seu arquivo de projeto.

    Essa alteração produz um único aplicativo de arquivo na publicação independente. Ele também mostra avisos de compatibilidade de arquivo único durante a compilação.

    <PropertyGroup>
        <PublishSingleFile>true</PublishSingleFile>
    </PropertyGroup>
    
  2. Publique o aplicativo para um identificador de tempo de execução específico usando dotnet publish -r <RID>

    O exemplo a seguir publica o aplicativo para Windows como um aplicativo de arquivo único independente.

    dotnet publish -r win-x64

    O exemplo a seguir publica o aplicativo para Linux como um aplicativo de arquivo único dependente da estrutura.

    dotnet publish -r linux-x64 --self-contained false

<PublishSingleFile> deve ser definido no arquivo de projeto para habilitar a análise de arquivo durante a compilação, mas também é possível passar essas opções como dotnet publish argumentos:

dotnet publish -r linux-x64 -p:PublishSingleFile=true --self-contained false

Para obter mais informações, consulte Publicar aplicativos .NET Core com .NET CLI.

Excluir arquivos da incorporação

Determinados arquivos podem ser explicitamente excluídos de serem incorporados no arquivo único, definindo os seguintes metadados:

<ExcludeFromSingleFile>true</ExcludeFromSingleFile>

Por exemplo, para colocar alguns arquivos no diretório de publicação, mas não agrupá-los no arquivo:

<ItemGroup>
  <Content Update="Plugin.dll">
    <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
    <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
  </Content>
</ItemGroup>

Incluir arquivos PDB dentro do pacote

O arquivo PDB para um assembly pode ser incorporado no próprio assembly (o .dll) usando a configuração abaixo. Como os símbolos fazem parte da montagem, eles também fazem parte do aplicativo:

<DebugType>embedded</DebugType>

Por exemplo, adicione a seguinte propriedade ao arquivo de projeto de um assembly para incorporar o arquivo PDB a esse assembly:

<PropertyGroup>
  <DebugType>embedded</DebugType>
</PropertyGroup>

Outras considerações

Os aplicativos de arquivo único têm todos os arquivos PDB relacionados ao lado do aplicativo, não agrupados por padrão. Se você quiser incluir PDBs dentro do assembly para projetos que você cria, defina como DebugTypeembedded. Consulte Incluir arquivos PDB dentro do pacote.

Os componentes C++ gerenciados não são adequados para a implantação de um único arquivo. Recomendamos que você escreva aplicativos em C# ou outra linguagem C++ não gerenciada para ser compatível com um único arquivo.

Bibliotecas nativas

Somente DLLs gerenciadas são agrupadas com o aplicativo em um único executável. Quando o aplicativo é iniciado, as DLLs gerenciadas são extraídas e carregadas na memória, evitando a extração para uma pasta. Com essa abordagem, os binários gerenciados são incorporados no pacote de arquivo único, mas os binários nativos do próprio tempo de execução principal são arquivos separados.

Para incorporar esses arquivos para extração e obter um arquivo de saída, defina a propriedade IncludeNativeLibrariesForSelfExtract como true.

A especificação IncludeAllContentForSelfExtract extrai todos os arquivos, incluindo os assemblies gerenciados, antes de executar o executável. Isso pode ser útil para problemas raros de compatibilidade de aplicativos.

Importante

Se a extração for usada, os arquivos serão extraídos para o disco antes que o aplicativo seja iniciado:

  • Se a DOTNET_BUNDLE_EXTRACT_BASE_DIR variável de ambiente for definida como um caminho, os arquivos serão extraídos para um diretório sob esse caminho.
  • Caso contrário, se estiver sendo executado no Linux ou macOS, os arquivos serão extraídos para um diretório em $HOME/.net.
  • Se estiver sendo executado no Windows, os arquivos são extraídos para um diretório em %TEMP%/.net.

Para evitar adulterações, esses diretórios não devem ser graváveis por usuários ou serviços com privilégios diferentes. Não use /tmp ou /var/tmp na maioria dos sistemas Linux e macOS.

Nota

Em alguns ambientes Linux, como em systemd, a extração padrão não funciona porque $HOME não está definida. Nesses casos, é recomendável que você defina $DOTNET_BUNDLE_EXTRACT_BASE_DIR explicitamente.

Para systemdo , uma boa alternativa é definir DOTNET_BUNDLE_EXTRACT_BASE_DIR no arquivo de unidade do seu serviço como %h/.net, que systemd se expande corretamente para $HOME/.net a conta que executa o serviço.

[Service]
Environment="DOTNET_BUNDLE_EXTRACT_BASE_DIR=%h/.net"

Incompatibilidade de API

Algumas APIs não são compatíveis com a implantação de um único arquivo. Os aplicativos podem precisar de modificação se usarem essas APIs. Se você usar uma estrutura ou pacote de terceiros, é possível que eles usem uma dessas APIs e precisem de modificação. A causa mais comum de problemas é a dependência de caminhos de arquivo para arquivos ou DLLs fornecidos com o aplicativo.

A tabela abaixo tem os detalhes relevantes da API da biblioteca de tempo de execução para uso em um único arquivo.

API Nota
Assembly.CodeBase Arremessos PlatformNotSupportedException.
Assembly.EscapedCodeBase Arremessos PlatformNotSupportedException.
Assembly.GetFile Arremessos IOException.
Assembly.GetFiles Arremessos IOException.
Assembly.Location Retorna uma cadeia de caracteres vazia.
AssemblyName.CodeBase Devoluções null.
AssemblyName.EscapedCodeBase Devoluções null.
Module.FullyQualifiedName Retorna uma cadeia de caracteres com o valor de <Unknown> ou lança uma exceção.
Marshal.GetHINSTANCE Devolve -1.
Module.Name Retorna uma cadeia de caracteres com o valor de <Unknown>.

Temos algumas recomendações para corrigir cenários comuns:

Pós-processamento de binários antes da agregação

Alguns fluxos de trabalho exigem pós-processamento de binários antes da agregação. Um exemplo comum é a assinatura. O dotnet SDK fornece pontos de extensão MSBuild para permitir o processamento de binários imediatamente antes da agregação de arquivo único. As APIs disponíveis são:

  • Um alvo PrepareForBundle que será chamado antes GenerateSingleFileBundle
  • Um <ItemGroup><FilesToBundle /></ItemGroup> contendo todos os arquivos que serão empacotados
  • Uma propriedade AppHostFile que especificará o modelo apphost. O pós-processamento pode querer excluir o apphost do processamento.

Conectar-se a isso envolve a criação de um destino que será executado entre PrepareForBundle e GenerateSingleFileBundle.

Considere o seguinte exemplo de nó de projeto Target .NET:

<Target Name="MySignedBundledFile" BeforeTargets="GenerateSingleFileBundle" DependsOnTargets="PrepareForBundle">

É possível que as ferramentas precisem copiar arquivos no processo de assinatura. Isso pode acontecer se o arquivo original for um item compartilhado que não pertence à compilação, por exemplo, o arquivo vem de um cache do NuGet. Nesse caso, espera-se que a ferramenta modifique o caminho do item correspondente FilesToBundle para apontar para a cópia modificada.

Compactar assemblies em aplicativos de arquivo único

Aplicativos de arquivo único podem ser criados com a compactação habilitada nos assemblies incorporados. Defina a propriedade EnableCompressionInSingleFile como true. O único arquivo produzido terá todos os assemblies incorporados compactados, o que pode reduzir significativamente o tamanho do executável.

A compressão tem um custo de desempenho. No início do aplicativo, os assemblies devem ser descompactados na memória, o que leva algum tempo. Recomendamos que você meça a alteração de tamanho e o custo de inicialização de habilitar a compactação antes de usá-la. O impacto pode variar significativamente entre diferentes aplicações.

Inspecionar um aplicativo de arquivo único

Os aplicativos de arquivo único podem ser inspecionados usando a ferramenta ILSpy. A ferramenta pode mostrar todos os arquivos agrupados no aplicativo e pode inspecionar o conteúdo de assemblies gerenciados.

Consulte também