Share via


Implementatie van één bestand

Het bundelen van alle toepassingsafhankelijke bestanden in één binair bestand biedt een toepassingsontwikkelaar de aantrekkelijke optie om de toepassing als één bestand te implementeren en te distribueren. Implementatie met één bestand is beschikbaar voor zowel het frameworkafhankelijke implementatiemodel als zelfstandige toepassingen.

De grootte van het enkele bestand in een zelfstandige toepassing is groot omdat het de runtime en de frameworkbibliotheken bevat. In .NET 6 kunt u afgekapt publiceren om de totale grootte van toepassingen die compatibel zijn met trim te verminderen. De optie voor implementatie van één bestand kan worden gecombineerd met de publicatieopties ReadyToRun en Trim .

Belangrijk

Als u één bestands-app wilt uitvoeren in Windows 7, moet u .NET Runtime 6.0.3 of hoger gebruiken.

Voorbeeldprojectbestand

Hier volgt een voorbeeldprojectbestand dat het publiceren van één bestand aangeeft:

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

Deze eigenschappen hebben de volgende functies:

  • PublishSingleFile. Hiermee schakelt u het publiceren van één bestand in. Hiermee worden ook waarschuwingen voor één bestand ingeschakeld tijdens dotnet build.
  • SelfContained. Bepaalt of de app zelfstandig of frameworkafhankelijk is.
  • RuntimeIdentifier. Hiermee geeft u het besturingssysteem en het CPU-type dat u wilt instellen. Wordt ook standaard ingesteld <SelfContained>true</SelfContained> .

Apps met één bestand zijn altijd specifiek voor het besturingssysteem en de architectuur. U moet publiceren voor elke configuratie, zoals Linux x64, Linux Arm64, Windows x64, enzovoort.

Runtimeconfiguratiebestanden, zoals *.runtimeconfig.json en *.deps.json, zijn opgenomen in het ene bestand. Als er een extra configuratiebestand nodig is, kunt u het naast het ene bestand plaatsen.

Een app met één bestand publiceren

Publiceer één bestandstoepassing met behulp van de opdracht dotnet publish .

  1. Voeg dit toe <PublishSingleFile>true</PublishSingleFile> aan het projectbestand.

    Deze wijziging produceert één bestands-app op zelfstandige publicatie. Er worden ook waarschuwingen voor compatibiliteit met één bestand weergegeven tijdens de build.

    <PropertyGroup>
        <PublishSingleFile>true</PublishSingleFile>
    </PropertyGroup>
    
  2. De app publiceren voor een specifieke runtime-id met behulp van dotnet publish -r <RID>

    In het volgende voorbeeld wordt de app voor Windows gepubliceerd als een zelfstandige toepassing voor één bestand.

    dotnet publish -r win-x64

    In het volgende voorbeeld wordt de app voor Linux gepubliceerd als een frameworkafhankelijke toepassing voor één bestand.

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

<PublishSingleFile> moet worden ingesteld in het projectbestand om bestandsanalyse in te schakelen tijdens de build, maar het is ook mogelijk om deze opties als dotnet publish argumenten door te geven:

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

Zie .NET Core-apps publiceren met .NET CLI voor meer informatie.

Bestanden uitsluiten van ingesloten bestanden

Bepaalde bestanden kunnen expliciet worden uitgesloten van ingesloten in het ene bestand door de volgende metagegevens in te stellen:

<ExcludeFromSingleFile>true</ExcludeFromSingleFile>

Als u bijvoorbeeld bepaalde bestanden in de publicatiemap wilt plaatsen, maar deze niet in het bestand wilt bundelen:

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

PDB-bestanden opnemen in de bundel

Het PDB-bestand voor een assembly kan worden ingesloten in de assembly zelf (de .dll) met behulp van de onderstaande instelling. Omdat de symbolen deel uitmaken van de assembly, maken ze ook deel uit van de toepassing:

<DebugType>embedded</DebugType>

Voeg bijvoorbeeld de volgende eigenschap toe aan het projectbestand van een assembly om het PDB-bestand in te sluiten voor die assembly:

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

Andere overwegingen

Toepassingen met één bestand hebben alle gerelateerde PDB-bestanden naast de toepassing, niet standaard gebundeld. Als u PDBS wilt opnemen in de assembly voor projecten die u bouwt, stelt u het in DebugType op embedded. Zie PDB-bestanden opnemen in de bundel.

Beheerde C++-onderdelen zijn niet geschikt voor implementatie van één bestand. U wordt aangeraden toepassingen te schrijven in C# of een andere niet-beheerde C++-taal om compatibel te zijn met één bestand.

Systeemeigen bibliotheken

Alleen beheerde DLL's worden gebundeld met de app in één uitvoerbaar bestand. Wanneer de app wordt gestart, worden de beheerde DLL's geëxtraheerd en in het geheugen geladen, waardoor de extractie naar een map wordt vermeden. Met deze methode worden de beheerde binaire bestanden ingesloten in de bundel met één bestand, maar de systeemeigen binaire bestanden van de kernruntime zelf zijn afzonderlijke bestanden.

Als u deze bestanden wilt insluiten voor extractie en één uitvoerbestand wilt ophalen, stelt u de eigenschap IncludeNativeLibrariesForSelfExtract in op true.

IncludeAllContentForSelfExtract Als u alle bestanden opgeeft, inclusief de beheerde assembly's, voordat u het uitvoerbare bestand uitvoert. Dit kan handig zijn voor zeldzame compatibiliteitsproblemen met toepassingen.

Belangrijk

Als extractie wordt gebruikt, worden de bestanden geëxtraheerd naar de schijf voordat de app wordt gestart:

  • Als de DOTNET_BUNDLE_EXTRACT_BASE_DIR omgevingsvariabele is ingesteld op een pad, worden de bestanden geëxtraheerd naar een map onder dat pad.
  • Anders worden de bestanden uitgepakt in een map onder $HOME/.netLinux of macOS.
  • Als de bestanden worden uitgevoerd in Windows, worden de bestanden geëxtraheerd naar een map onder %TEMP%/.net.

Om manipulatie te voorkomen, mogen deze mappen niet beschrijfbaar zijn door gebruikers of services met verschillende bevoegdheden. Gebruik /tmp of /var/tmp niet op de meeste Linux- en macOS-systemen.

Notitie

In sommige Linux-omgevingen, zoals onder systemd, werkt de standaardextractie niet omdat $HOME deze niet is gedefinieerd. In dergelijke gevallen wordt u aangeraden expliciet in te stellen $DOTNET_BUNDLE_EXTRACT_BASE_DIR .

Een systemdgoed alternatief is om te definiëren DOTNET_BUNDLE_EXTRACT_BASE_DIR in het eenheidsbestand van uw service als %h/.net, dat systemd correct wordt uitgebreid voor $HOME/.net het account waarop de service wordt uitgevoerd.

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

API-incompatibiliteit

Sommige API's zijn niet compatibel met implementatie van één bestand. Toepassingen moeten mogelijk worden gewijzigd als ze deze API's gebruiken. Als u een framework of pakket van derden gebruikt, is het mogelijk dat ze een van deze API's gebruiken en moeten worden gewijzigd. De meest voorkomende oorzaak van problemen is de afhankelijkheid van bestandspaden voor bestanden of DLL's die bij de toepassing worden geleverd.

De onderstaande tabel bevat de relevante api-gegevens van de runtimebibliotheek voor het gebruik van één bestand.

API Notitie
Assembly.CodeBase Gooit PlatformNotSupportedException.
Assembly.EscapedCodeBase Gooit PlatformNotSupportedException.
Assembly.GetFile Gooit IOException.
Assembly.GetFiles Gooit IOException.
Assembly.Location Retourneert een lege tekenreeks.
AssemblyName.CodeBase Retourneert null.
AssemblyName.EscapedCodeBase Retourneert null.
Module.FullyQualifiedName Retourneert een tekenreeks met de waarde van <Unknown> of genereert een uitzondering.
Marshal.GetHINSTANCE Retourneert -1.
Module.Name Retourneert een tekenreeks met de waarde van <Unknown>.

Er zijn enkele aanbevelingen voor het oplossen van veelvoorkomende scenario's:

  • Als u bestanden naast het uitvoerbare bestand wilt openen, gebruikt u AppContext.BaseDirectory.

  • Als u de bestandsnaam van het uitvoerbare bestand wilt vinden, gebruikt u het eerste element van Environment.GetCommandLineArgs(), of begint met .NET 6, gebruikt u de bestandsnaam van ProcessPath.

  • Als u wilt voorkomen dat losse bestanden volledig worden verzonden, kunt u overwegen ingesloten resources te gebruiken.

Binaire bestanden na verwerking vóór bundeling

Sommige werkstromen vereisen naverwerking van binaire bestanden voordat ze worden gebundeld. Een veelvoorkomend voorbeeld is ondertekening. De dotnet SDK biedt MSBuild-extensiepunten voor het verwerken van binaire bestanden net voordat één bestand wordt gebundeld. De beschikbare API's zijn:

  • Een doel PrepareForBundle dat eerder wordt aangeroepen GenerateSingleFileBundle
  • Een <ItemGroup><FilesToBundle /></ItemGroup> met alle bestanden die worden gebundeld
  • Een eigenschap AppHostFile waarmee de apphost-sjabloon wordt opgegeven. Naverwerking wil de apphost mogelijk uitsluiten van verwerking.

Als u dit wilt aansluiten, moet u een doel maken dat wordt uitgevoerd tussen PrepareForBundle en GenerateSingleFileBundle.

Bekijk het volgende voorbeeld van een .NET-projectknooppunt Target :

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

Het is mogelijk dat hulpprogramma's bestanden moeten kopiëren tijdens het ondertekenen. Dit kan gebeuren als het oorspronkelijke bestand een gedeeld item is dat niet eigendom is van de build, bijvoorbeeld dat het bestand afkomstig is van een NuGet-cache. In dat geval wordt verwacht dat het hulpprogramma het pad van het bijbehorende FilesToBundle item wijzigt om naar de gewijzigde kopie te verwijzen.

Assembly's comprimeren in apps met één bestand

Apps met één bestand kunnen worden gemaakt met compressie ingeschakeld voor de ingesloten assembly's. Stel de eigenschap EnableCompressionInSingleFile in op true. Het bestand dat wordt geproduceerd, heeft alle ingesloten assembly's gecomprimeerd, waardoor de grootte van het uitvoerbare bestand aanzienlijk kan worden verkleind.

Compressie wordt geleverd met een prestatiekosten. Bij het starten van de toepassing moeten de assembly's worden gedecomprimeerd in het geheugen, wat enige tijd kost. U wordt aangeraden zowel de groottewijziging als de opstartkosten voor het inschakelen van compressie te meten voordat u deze gebruikt. De impact kan aanzienlijk verschillen tussen verschillende toepassingen.

Een app met één bestand controleren

Apps met één bestand kunnen worden geïnspecteerd met behulp van het hulpprogramma ILSpy. Het hulpprogramma kan alle bestanden weergeven die zijn gebundeld in de toepassing en kan de inhoud van beheerde assembly's inspecteren.

Zie ook