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 tijdensdotnet 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.
Een app met één bestand publiceren
Publiceer één bestandstoepassing met behulp van de opdracht dotnet publish .
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>
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/.net
Linux 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 systemd
goed 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 aangeroepenGenerateSingleFileBundle
- 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.