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 struktury, jak i aplikacji samodzielnie zawartych.

Rozmiar pojedynczego pliku w aplikacji samodzielnej jest duży, ponieważ obejmuje środowisko uruchomieniowe i biblioteki struktury. Na platformie .NET 6 można opublikować przycięte, aby zmniejszyć całkowity rozmiar aplikacji zgodnych z przycinania. 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 dotyczące pojedynczego pliku podczas wykonywania dotnet buildpolecenia .
  • SelfContained. Określa, czy aplikacja jest zależna od siebie, czy struktury.
  • RuntimeIdentifier. Określa docelowy typ systemu operacyjnego i procesora CPU. <SelfContained>true</SelfContained> Ustawia również domyślnie.

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

Pliki konfiguracji środowiska uruchomieniowego, takie jak *.runtimeconfig.json i *.deps.json, są uwzględniane w jednym pliku. Jeśli potrzebny jest dodatkowy plik konfiguracji, możesz umieścić go obok pojedynczego 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 platformy z pojedynczym plikiem.

    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 Publikowanie aplikacji platformy .NET Core za pomocą interfejsu wiersza polecenia platformy .NET.

Wykluczanie plików z osadzania

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 publikowania, ale nie umieścić ich w pliku:

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

Dołączanie plików PDB do pakietu

Plik PDB zestawu można osadzić w samym zestawie () .dllprzy 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 wraz z aplikacją, a nie są domyślnie powiązane. 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, co pozwala uniknąć 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 na potrzeby wyodrębniania i pobrać jeden plik wyjściowy, ustaw właściwość IncludeNativeLibrariesForSelfExtract na truewartość .

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 obszarze $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 przypadku systemdprogramu dobrą alternatywą jest zdefiniowanie DOTNET_BUNDLE_EXTRACT_BASE_DIR w pliku jednostkowym usługi jako %h/.net, który rozszerza się poprawnie dla $HOME/.net konta, na którym systemd jest uruchomiona usługa.

[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 struktury lub pakietu innej firmy, możliwe jest, że mogą używać jednego z tych interfejsów API i wymagać 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.

interfejs API Uwaga
Assembly.CodeBase Zgłasza element PlatformNotSupportedException.
Assembly.EscapedCodeBase Zgłasza element PlatformNotSupportedException.
Assembly.GetFile Zgłasza element IOException.
Assembly.GetFiles Zgłasza element 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 po przetworzeniu 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. Zestaw DOTNET SDK udostępnia punkty rozszerzenia MSBuild, aby umożliwić przetwarzanie plików binarnych tuż przed tworzeniem pakietów pojedynczego pliku. Dostępne interfejsy API to:

  • Element docelowy PrepareForBundle , który będzie wywoływany przed GenerateSingleFileBundle
  • Plik <ItemGroup><FilesToBundle /></ItemGroup> zawierający wszystkie pliki, które zostaną połączone
  • Właściwość AppHostFile określająca szablon apphost. Przetwarzanie końcowe może chcieć wykluczyć host apphost z przetwarzania.

Aby połączyć się z tym elementem, należy utworzyć obiekt docelowy, który zostanie wykonany 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 będzie miał skompresowane wszystkie zestawy osadzone, co może znacząco 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ż