Distribution med en fil

Genom att paketera alla programberoende filer i en enda binär fil får en programutvecklare det attraktiva alternativet att distribuera och distribuera programmet som en enda fil. Distribution med en fil är tillgänglig för både den ramverksberoende distributionsmodellen och fristående program.

Storleken på den enskilda filen i ett fristående program är stor eftersom den innehåller körnings- och ramverksbiblioteken. I .NET 6 kan du publicera trimmade för att minska den totala storleken på trimkompatibla program. Distributionsalternativet för en enskild fil kan kombineras med publiceringsalternativen ReadyToRun och Trim .

Viktigt!

Om du vill köra en enskild filapp i Windows 7 måste du använda .NET Runtime 6.0.3 eller senare.

Exempelprojektfil

Här är en exempelprojektfil som anger enkel filpublicering:

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

Dessa egenskaper har följande funktioner:

  • PublishSingleFile. Aktiverar enkel filpublicering. Aktiverar även enstaka filvarningar under dotnet build.
  • SelfContained. Avgör om appen är fristående eller ramverksberoende.
  • RuntimeIdentifier. Anger vilken operativsystem- och CPU-typ du riktar in dig på. Anger <SelfContained>true</SelfContained> också som standard.

Appar med en fil är alltid os- och arkitekturspecifika. Du måste publicera för varje konfiguration, till exempel Linux x64, Linux Arm64, Windows x64 och så vidare.

Körningskonfigurationsfiler, till exempel *.runtimeconfig.json och *.deps.json, ingår i den enskilda filen. Om du behöver en extra konfigurationsfil kan du placera den bredvid den enskilda filen.

Publicera en enfilsapp

Publicera ett enda filprogram med hjälp av dotnet-publiceringskommandot.

  1. Lägg till <PublishSingleFile>true</PublishSingleFile> i projektfilen.

    Den här ändringen genererar en enskild filapp vid fristående publicering. Den visar också varningar om enkel filkompatibilitet under kompilering.

    <PropertyGroup>
        <PublishSingleFile>true</PublishSingleFile>
    </PropertyGroup>
    
  2. Publicera appen för en specifik körningsidentifierare med hjälp av dotnet publish -r <RID>

    I följande exempel publiceras appen för Windows som ett fristående program med en enda fil.

    dotnet publish -r win-x64

    I följande exempel publiceras appen för Linux som ett ramverksberoende program med en enda fil.

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

<PublishSingleFile> bör anges i projektfilen för att aktivera filanalys under bygget, men det är också möjligt att skicka dessa alternativ som dotnet publish argument:

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

Mer information finns i Publicera .NET Core-appar med .NET CLI.

Undanta filer från att bäddas in

Vissa filer kan uttryckligen undantas från att bäddas in i den enskilda filen genom att ange följande metadata:

<ExcludeFromSingleFile>true</ExcludeFromSingleFile>

Om du till exempel vill placera vissa filer i publiceringskatalogen men inte paket dem i filen:

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

Inkludera PDB-filer i paketet

PDB-filen för en sammansättning kan bäddas in i själva sammansättningen () .dllmed hjälp av inställningen nedan. Eftersom symbolerna ingår i sammansättningen är de också en del av programmet:

<DebugType>embedded</DebugType>

Lägg till exempel till följande egenskap i projektfilen för en sammansättning för att bädda in PDB-filen i den sammansättningen:

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

Övriga beaktanden

Enfilsprogram har alla relaterade PDB-filer tillsammans med programmet, inte paketerade som standard. Om du vill inkludera PDF-filer i sammansättningen för projekt som du skapar anger du DebugType till embedded. Se Inkludera PDB-filer i paketet.

Hanterade C++-komponenter passar inte bra för distribution av en enskild fil. Vi rekommenderar att du skriver program i C# eller ett annat icke-hanterat C++-språk för att vara en enda filkompatibel.

Interna bibliotek

Endast hanterade DLL:er paketeras med appen i en enda körbar fil. När appen startar extraheras och läses de hanterade DLL:erna in i minnet, vilket undviker extrahering till en mapp. Med den här metoden bäddas de hanterade binärfilerna in i det enskilda filpaketet, men de interna binärfilerna för själva kärnkörningen är separata filer.

Om du vill bädda in filerna för extrahering och hämta en utdatafil anger du egenskapen IncludeNativeLibrariesForSelfExtract till true.

Om du anger IncludeAllContentForSelfExtract extraheras alla filer, inklusive de hanterade sammansättningarna, innan du kör den körbara filen. Detta kan vara användbart för sällsynta programkompatibilitetsproblem.

Viktigt!

Om extrahering används extraheras filerna till disken innan appen startar:

  • DOTNET_BUNDLE_EXTRACT_BASE_DIR Om miljövariabeln är inställd på en sökväg extraheras filerna till en katalog under den sökvägen.
  • Annars, om de körs på Linux eller macOS, extraheras filerna till en katalog under $HOME/.net.
  • Om de körs i Windows extraheras filerna till en katalog under %TEMP%/.net.

För att förhindra manipulering bör dessa kataloger inte skrivas av användare eller tjänster med olika behörigheter. Använd inte /tmp eller /var/tmp på de flesta Linux- och macOS-system.

Kommentar

I vissa Linux-miljöer, till exempel under systemd, fungerar inte standardextraheringen eftersom $HOME den inte har definierats. I sådana fall rekommenderar vi att du anger $DOTNET_BUNDLE_EXTRACT_BASE_DIR explicit.

För systemdär ett bra alternativ att definiera DOTNET_BUNDLE_EXTRACT_BASE_DIR i tjänstens enhetsfil som %h/.net, som expanderas korrekt till $HOME/.net för kontot som systemd kör tjänsten.

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

API-inkompatibilitet

Vissa API:er är inte kompatibla med distribution av en enda fil. Program kan kräva ändringar om de använder dessa API:er. Om du använder ett ramverk eller paket från tredje part är det möjligt att de använder något av dessa API:er och behöver ändras. Den vanligaste orsaken till problem är beroende av filsökvägar för filer eller DLL:er som levereras med programmet.

Tabellen nedan innehåller relevant API-information för körningsbiblioteket för enkel filanvändning.

API Kommentar
Assembly.CodeBase Kastar PlatformNotSupportedException.
Assembly.EscapedCodeBase Kastar PlatformNotSupportedException.
Assembly.GetFile Kastar IOException.
Assembly.GetFiles Kastar IOException.
Assembly.Location Returnerar en tom sträng.
AssemblyName.CodeBase Returnerar null.
AssemblyName.EscapedCodeBase Returnerar null.
Module.FullyQualifiedName Returnerar en sträng med värdet <Unknown> för eller genererar ett undantag.
Marshal.GetHINSTANCE Returnerar -1.
Module.Name Returnerar en sträng med värdet <Unknown>.

Vi har några rekommendationer för att åtgärda vanliga scenarier:

Binärfiler efter bearbetning före paketering

Vissa arbetsflöden kräver efterbearbetning av binärfiler innan paketering. Ett vanligt exempel är signering. Dotnet SDK tillhandahåller MSBuild-tilläggspunkter för att tillåta bearbetning av binärfiler precis före paketering med en fil. De tillgängliga API:erna är:

  • Ett mål PrepareForBundle som ska anropas före GenerateSingleFileBundle
  • En <ItemGroup><FilesToBundle /></ItemGroup> som innehåller alla filer som ska paketeras
  • En egenskap AppHostFile som anger mallen apphost. Efterbearbetningen kanske vill undanta apphost från bearbetning.

Att ansluta till detta innebär att skapa ett mål som ska köras mellan PrepareForBundle och GenerateSingleFileBundle.

Överväg följande .NET-projektnodexempel Target :

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

Det är möjligt att verktyg måste kopiera filer under signeringsprocessen. Det kan inträffa om den ursprungliga filen är ett delat objekt som inte ägs av bygget, till exempel om filen kommer från en NuGet-cache. I så fall förväntas verktyget ändra sökvägen till motsvarande FilesToBundle objekt så att det pekar på den ändrade kopian.

Komprimera sammansättningar i appar med en fil

Appar med en fil kan skapas med komprimering aktiverat på de inbäddade sammansättningarna. Ange egenskapen EnableCompressionInSingleFile till true. Den enda fil som skapas kommer att ha alla inbäddade sammansättningar komprimerade, vilket avsevärt kan minska storleken på den körbara filen.

Komprimering medför en prestandakostnad. Vid programstart måste sammansättningarna dekomprimeras till minnet, vilket tar lite tid. Vi rekommenderar att du mäter både storleksändringen och startkostnaden för att aktivera komprimering innan du använder den. Effekten kan variera avsevärt mellan olika program.

Inspektera en enfilsapp

Appar med en fil kan inspekteras med hjälp av ILSpy-verktyget. Verktyget kan visa alla filer som paketeras i programmet och kan granska innehållet i hanterade sammansättningar.

Se även