Udostępnij za pośrednictwem


Wdrażanie pojedynczego pliku

Łączenie wszystkich plików zależnych od aplikacji w jeden plik binarny zapewnia deweloperowi aplikacji atrakcyjną opcję wdrażania i dystrybuowania aplikacji jako pojedynczego pliku. Wdrożenie jednoplikowe jest dostępne zarówno dla modelu wdrażania zależnego od platformy, jak i samodzielnych aplikacji.

Rozmiar pojedynczego pliku w aplikacji samodzielnej jest duży, ponieważ obejmuje środowisko uruchomieniowe i biblioteki struktury. W .NET 6 można opublikować przyciętą wersję, aby zmniejszyć całkowity rozmiar aplikacji zgodnych z przycinaniem. Opcja wdrożenia pojedynczego pliku może być połączona z opcjami publikowania ReadyToRun i Trim .

Ważne

Aby uruchomić pojedynczą aplikację plików w systemie Windows 7, musisz użyć środowiska uruchomieniowego .NET Runtime 6.0.3 lub nowszego.

Przykładowy plik projektu

Oto przykładowy plik projektu, który określa publikowanie pojedynczego pliku:

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

Te właściwości mają następujące funkcje:

  • PublishSingleFile. Umożliwia publikowanie pojedynczego pliku. Włącza również ostrzeżenia w odniesieniu do pojedynczych plików podczas dotnet build.
  • SelfContained. Określa, czy aplikacja jest samodzielna, czy zależna od frameworka.
  • RuntimeIdentifier. Określa docelowy typ systemu operacyjnego i procesora CPU. Również ustawia <SelfContained>true</SelfContained> domyślnie.

Pojedyncze aplikacje plików są zawsze specyficzne dla systemu operacyjnego i architektury. Musisz opublikować dla każdej konfiguracji, na przykład Linux x64, Linux Arm64, Windows x64 itd.

Pliki konfiguracji środowiska uruchomieniowego, takie jak *.runtimeconfig.json i *.deps.json, są uwzględniane w jednym pliku.

Publikowanie aplikacji z jednym plikiem

Publikowanie pojedynczej aplikacji plików przy użyciu polecenia dotnet publish .

  1. Dodaj <PublishSingleFile>true</PublishSingleFile> do pliku projektu.

    Ta zmiana powoduje utworzenie pojedynczej aplikacji plików w ramach samodzielnego publikowania. Wyświetlane są również ostrzeżenia dotyczące zgodności z pojedynczym plikiem podczas kompilacji.

    <PropertyGroup>
        <PublishSingleFile>true</PublishSingleFile>
    </PropertyGroup>
    
  2. Publikowanie aplikacji dla określonego identyfikatora środowiska uruchomieniowego przy użyciu polecenia dotnet publish -r <RID>

    Poniższy przykład publikuje aplikację dla systemu Windows jako samodzielną aplikację z pojedynczym plikiem.

    dotnet publish -r win-x64

    Poniższy przykład publikuje aplikację dla systemu Linux jako aplikację zależną od frameworku w formie pojedynczego pliku.

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

<PublishSingleFile> Należy ustawić w pliku projektu, aby włączyć analizę plików podczas kompilacji, ale istnieje również możliwość przekazania tych opcji jako dotnet publish argumentów:

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

Aby uzyskać więcej informacji, zobacz Omówienie publikowania aplikacji platformy .NET.

Wyklucz pliki z osadzenia

Niektóre pliki można jawnie wykluczyć z osadowania w jednym pliku, ustawiając następujące metadane:

<ExcludeFromSingleFile>true</ExcludeFromSingleFile>

Aby na przykład umieścić niektóre pliki w katalogu publikacji, ale nie dołączyć ich do paczki:

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

Dołączanie plików PDB do pakietu

Plik PDB dla zestawu można osadzić w samym zestawie (.dll) przy użyciu poniższego ustawienia. Ponieważ symbole są częścią zestawu, są one również częścią aplikacji:

<DebugType>embedded</DebugType>

Na przykład dodaj następującą właściwość do pliku projektu zestawu, aby osadzić plik PDB w tym zestawie:

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

Inne uwagi

Aplikacje z jednym plikiem mają wszystkie powiązane pliki PDB obok aplikacji i nie są domyślnie łączone w jeden pakiet. Jeśli chcesz dołączyć pliki PDB do zestawu dla projektów, które tworzysz, ustaw wartość DebugTypeembedded. Zobacz Dołączanie plików PDB wewnątrz pakietu.

Zarządzane składniki języka C++ nie nadają się do wdrożenia pojedynczego pliku. Zalecamy pisanie aplikacji w języku C# lub innym niezarządzanym języku C++, aby były zgodne z pojedynczym plikiem.

Biblioteki natywne

Tylko zarządzane biblioteki DLL są połączone z aplikacją w jeden plik wykonywalny. Po uruchomieniu aplikacji zarządzane biblioteki DLL są wyodrębniane i ładowane w pamięci, unikając wyodrębniania do folderu. W przypadku tego podejścia zarządzane pliki binarne są osadzone w jednym pakiecie plików, ale pliki binarne natywne samego środowiska uruchomieniowego podstawowego są oddzielnymi plikami.

Aby osadzić te pliki do wyodrębniania i uzyskać jeden plik wyjściowy, ustaw właściwość IncludeNativeLibrariesForSelfExtract na true wartość.

Określenie IncludeAllContentForSelfExtract wyodrębnia wszystkie pliki, w tym zarządzane zestawy, przed uruchomieniem pliku wykonywalnego. Może to być przydatne w przypadku rzadkich problemów ze zgodnością aplikacji.

Ważne

Jeśli wyodrębnianie jest używane, pliki są wyodrębniane na dysk przed uruchomieniem aplikacji:

  • Jeśli zmienna DOTNET_BUNDLE_EXTRACT_BASE_DIR środowiskowa jest ustawiona na ścieżkę, pliki są wyodrębniane do katalogu pod tą ścieżką.
  • W przeciwnym razie, w przypadku uruchamiania w systemie Linux lub macOS, pliki są wyodrębniane do katalogu w lokalizacji $HOME/.net.
  • W przypadku uruchamiania w systemie Windows pliki są wyodrębniane do katalogu w obszarze %TEMP%/.net.

Aby zapobiec manipulacji, te katalogi nie powinny być zapisywalne przez użytkowników lub usługi z różnymi uprawnieniami. Nie używaj /tmp ani /var/tmp w większości systemów Linux i macOS.

Uwaga

W niektórych środowiskach systemu Linux, takich jak w obszarze systemd, domyślne wyodrębnianie nie działa, ponieważ $HOME nie jest zdefiniowane. W takich przypadkach zaleca się jawne ustawienie $DOTNET_BUNDLE_EXTRACT_BASE_DIR .

W systemd dobrą alternatywą jest zdefiniowanie DOTNET_BUNDLE_EXTRACT_BASE_DIR w pliku jednostkowym usługi jako %h/.net, co poprawnie rozszerza się na $HOME/.net dla konta uruchamiającego usługę.

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

Niezgodność interfejsu API

Niektóre interfejsy API nie są zgodne z wdrożeniem pojedynczego pliku. Aplikacje mogą wymagać modyfikacji, jeśli korzystają z tych interfejsów API. Jeśli używasz zewnętrznego frameworka lub pakietu, możliwe jest, że mogą korzystać z jednego z tych interfejsów API i wymagają modyfikacji. Najczęstszą przyczyną problemów jest zależność od ścieżek plików lub bibliotek DLL dostarczanych z aplikacją.

Poniższa tabela zawiera szczegółowe informacje o interfejsie API biblioteki środowiska uruchomieniowego na potrzeby użycia pojedynczego pliku.

API Uwaga
Assembly.CodeBase Zgłasza element PlatformNotSupportedException.
Assembly.EscapedCodeBase Rzuca PlatformNotSupportedException.
Assembly.GetFile Zgłasza element IOException.
Assembly.GetFiles Rzuca IOException.
Assembly.Location Zwraca pusty ciąg.
AssemblyName.CodeBase Zwraca wartość null.
AssemblyName.EscapedCodeBase Zwraca wartość null.
Module.FullyQualifiedName Zwraca ciąg z wartością <Unknown> lub zgłasza wyjątek.
Marshal.GetHINSTANCE Zwraca wartość -1.
Module.Name Zwraca ciąg z wartością <Unknown>.

Mamy kilka zaleceń dotyczących naprawiania typowych scenariuszy:

Przetwarzanie plików binarnych przed tworzeniem pakietów

Niektóre przepływy pracy wymagają przetwarzania końcowego plików binarnych przed tworzeniem pakietów. Typowym przykładem jest podpisywanie. Pakiet SDK .NET udostępnia punkty rozszerzenia MSBuild, aby umożliwić przetwarzanie plików binarnych tuż przed łączeniem w jeden plik. Dostępne interfejsy API to:

  • Element docelowy PrepareForBundle, który jest wywoływany przed GenerateSingleFileBundle
  • Plik <ItemGroup><FilesToBundle /></ItemGroup> zawierający wszystkie pliki, które mają być powiązane
  • Właściwość AppHostFile określająca szablon apphost. Przetwarzanie wtórne może chcieć wykluczyć aplikację hostującą z przetwarzania.

Aby podłączyć tę funkcję, należy utworzyć obiekt docelowy, który jest wykonywany między elementami PrepareForBundle i GenerateSingleFileBundle.

Rozważmy następujący przykładowy węzeł projektu Target platformy .NET:

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

Istnieje możliwość, że narzędzia będą musiały kopiować pliki w procesie podpisywania. Może się tak zdarzyć, jeśli oryginalny plik jest elementem udostępnionym, który nie jest własnością kompilacji, na przykład plik pochodzi z pamięci podręcznej NuGet. W takim przypadku oczekuje się, że narzędzie zmodyfikuje ścieżkę odpowiedniego FilesToBundle elementu, aby wskazywało zmodyfikowaną kopię.

Kompresowanie zestawów w aplikacjach jednoplikowych

Aplikacje z jednym plikiem można tworzyć z włączoną kompresją w zestawach osadzonych. Ustaw właściwość EnableCompressionInSingleFile na true. Wygenerowany pojedynczy plik ma skompresowane wszystkie zestawy osadzone, co może znacznie zmniejszyć rozmiar pliku wykonywalnego.

Kompresja wiąże się z kosztem wydajności. Po uruchomieniu aplikacji zestawy muszą zostać zdekompresowane do pamięci, co zajmuje trochę czasu. Zalecamy mierzenie zarówno zmiany rozmiaru, jak i kosztu uruchamiania włączania kompresji przed jego użyciem. Wpływ może się znacznie różnić między różnymi aplikacjami.

Inspekcja aplikacji z jednym plikiem

Aplikacje z pojedynczymi plikami można sprawdzić przy użyciu narzędzia ILSpy. Narzędzie może wyświetlić wszystkie pliki dołączone do aplikacji i sprawdzić zawartość zarządzanych zestawów.

Zobacz też