単一ファイルのデプロイ

アプリケーションに依存するすべてのファイルを単一のバイナリにバンドルすることで、アプリケーション開発者は、アプリケーションを単一ファイルとして配置し、配布することができます。 フレームワークに依存するデプロイ モデル自己完結型アプリケーションの両方で、単一ファイルの配置が可能です。

自己完結型アプリケーション内にある単一ファイルは、ランタイム ライブラリとフレームワーク ライブラリが含まれるため、サイズが大きいです。 .NET 6 では、トリミングを発行して、トリム互換アプリケーションの合計サイズを小さくできます。 単一ファイルの配置オプションは、ReadyToRunTrim の発行オプションと組み合わせることができます。

[重要] Windows 7 で単一ファイル アプリを実行するには、.NET Runtime 6.0.3 以降を使用する必要があります。

サンプル プロジェクト ファイル

単一ファイルの発行を指定するサンプル プロジェクト ファイルを次に示します。

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

これらのプロパティには、次の関数があります。

  • PublishSingleFile。 単一ファイルの発行を有効にします。 また、dotnet build 時の単一ファイルの警告を有効にします。
  • SelfContained. アプリが自己完結型またはフレームワーク依存であるかを判断します。
  • RuntimeIdentifier. ターゲットとする OS と CPU の種類を指定します。 また、既定で <SelfContained>true</SelfContained> が設定されます。

単一ファイル アプリは常に OS とアーキテクチャに固有です。 Linux x64、Linux Arm64、Windows x64 など、構成ごとに発行する必要があります。

ランタイム構成ファイル (*.runtimeconfig.json*.deps.json など) は、単一ファイルに含まれています。 追加の構成ファイルが必要な場合は、その単一ファイルの傍らに置くことができます。

単一ファイル アプリを発行する

dotnet publish コマンドを使用して、単一ファイル アプリケーションを発行します。

  1. お使いのプロジェクト ファイルに <PublishSingleFile>true</PublishSingleFile> を追加します。

    この変更により、自己完結型の発行で単一ファイル アプリが生成されます。 また、ビルド時に単一ファイルの互換性に関する警告も表示されます。

    <PropertyGroup>
        <PublishSingleFile>true</PublishSingleFile>
    </PropertyGroup>
    
  2. dotnet publish -r <RID> を使用して、特定のランタイム識別子のアプリを発行します

    次の例では、Windows 用のアプリが自己完結型の単一ファイル アプリケーションとして発行されます。

    dotnet publish -r win-x64

    次の例では、Linux 用のアプリがフレームワークに依存する単一ファイル アプリケーションとして発行されます。

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

プロジェクト ファイルに <PublishSingleFile> を設定し、ビルド時にファイル分析を有効にすることもできますが、これらのオプションを dotnet publish 引数として渡すことも可能です。

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

詳細については、「.NET CLI を使用して .NET Core アプリを発行する」を参照してください。

ファイルを埋め込み対象から除外する

次のメタデータを設定すると、特定のファイルを単一ファイルの埋め込み対象から明示的に除外することができます。

<ExcludeFromSingleFile>true</ExcludeFromSingleFile>

たとえば、いくつかのファイルを発行ディレクトリに配置するが、そのファイルにはバンドルしない場合などです。

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

バンドル内に PDB ファイルを含める

アセンブリの PDB ファイルは、次の設定を使用して、アセンブリ自体 (.dll) に埋め込むことができます。 シンボルはアセンブリの一部であるため、アプリケーションの一部でもあります。

<DebugType>embedded</DebugType>

たとえば、アセンブリに PDB ファイルを埋め込むには、そのアセンブリのプロジェクト ファイルに次のプロパティを追加します。

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

その他の考慮事項

単一ファイル アプリケーションには、関連するすべての PDB ファイルがアプリケーションと共に含まれますが、既定ではバンドルされていません。 ビルドするプロジェクトのアセンブリ内に PDB を含めるには、DebugTypeembedded に設定します。 「バンドル内に PDB ファイルを含める」を参照してください。

マネージド C++ コンポーネントは、単一ファイルの配置には適していません。 単一ファイルとの互換性を確保するには、アプリケーションを C# または別の非マネージド C++ 言語で記述することをお勧めします。

ネイティブ ライブラリ

マネージド DLL だけがアプリにバンドルされて、1 つの実行可能ファイルになります。 アプリが起動すると、マネージド DLL が抽出されてメモリに読み込まれ、フォルダーには抽出されません。 この手法により、マネージド バイナリは単一ファイル バンドルに埋め込まれますが、コア ランタイム自体のネイティブ バイナリは別個のファイルになります。

抽出用にそれらのファイルを埋め込み、1 つの出力ファイルを取得するには、IncludeNativeLibrariesForSelfExtract プロパティを true に設定します。

IncludeAllContentForSelfExtract を指定すると、実行可能ファイルを実行する前にすべてのファイル (マネージド アセンブリも) が展開されます。 これは、まれなアプリケーション互換性の問題に役立つ場合があります。

重要

展開が使用されている場合、アプリが起動する前にファイルがディスクに展開されます。

  • DOTNET_BUNDLE_EXTRACT_BASE_DIR 環境変数がパスに設定されている場合、ファイルはそのパスの下のディレクトリに抽出されます。
  • それ以外の場合、Linux または macOS で実行されている場合は、ファイルは $HOME/.net の下のディレクトリに抽出されます。
  • Windows で実行されている場合は、%TEMP%/.net の下のディレクトリにファイルが展開されます。

改ざんを防ぐために、これらのディレクトリは、異なる権限を持つユーザーまたはサービスによる書き込みを可能にしないでください。 ほとんどの Linux および macOS システムでは、/tmp または /var/tmp を使用しないでください。

注意

一部の Linux 環境 (たとえば、systemd の下) では、$HOME が定義されていないため、既定の抽出は機能しません。 このような場合は、$DOTNET_BUNDLE_EXTRACT_BASE_DIR を明示的に設定することをお勧めします。

systemd の場合、サービスのユニット ファイルで DOTNET_BUNDLE_EXTRACT_BASE_DIR%h/.net として定義することをお勧めします。これによって、systemd では、サービスを実行しているアカウントの $HOME/.net に正しく展開されます。

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

API の非互換性

一部の API は、単一ファイルの配置と互換性がありません。 アプリケーションでこれらの API を使用する場合は、変更が必要になることがあります。 サードパーティのフレームワークまたはパッケージを使用する場合、これらの API のいずれかが使用されているために、変更が必要になる可能性があります。 問題の最も一般的な原因は、アプリケーションに付属するファイルまたは DLL のファイル パスに依存していることです。

次の表に、単一ファイルの使用に関連するランタイム ライブラリ API の詳細を示します。

API Note
Assembly.CodeBase PlatformNotSupportedException をスローします。
Assembly.EscapedCodeBase PlatformNotSupportedException をスローします。
Assembly.GetFile IOException をスローします。
Assembly.GetFiles IOException をスローします。
Assembly.Location 空の文字列を返します。
AssemblyName.CodeBase null を返します。
AssemblyName.EscapedCodeBase null を返します。
Module.FullyQualifiedName 値が <Unknown> である文字列が返されるか、例外がスローされます。
Marshal.GetHINSTANCE -1 を返します。
Module.Name 値が <Unknown> である文字列が返されます。

一般的なシナリオを修正するための推奨事項がいくつかあります。

  • 実行可能ファイルの隣にあるファイルにアクセスするには、AppContext.BaseDirectory を使用します。

  • 実行可能ファイルのファイル名を見つけるには、Environment.GetCommandLineArgs() の先頭の要素を使用するか、.NET 6 以降では、ProcessPath から返されるファイル名を使用します。

  • Loose ファイルが完全に配布されないようにするには、埋め込みリソースを使用することを検討します。

バンドル前のバイナリの後処理

一部のワークフローでは、バンドルする前にバイナリの後処理が必要です。 一般的な例は、署名です。 dotnet SDK には、単一ファイルバンドルの直前にバイナリを処理できるようにするための MSBuild 拡張ポイントが用意されています。 使用可能な API は次のとおりです。

  • GenerateSingleFileBundle の前に呼び出されるターゲット PrepareForBundle
  • バンドルされるすべてのファイルを含む <ItemGroup><FilesToBundle /></ItemGroup>
  • apphost テンプレートを指定するプロパティ AppHostFile。 後処理では、apphost を処理から除外した方がよい場合があります。

これをプラグインするには、PrepareForBundleGenerateSingleFileBundle の間で実行されるターゲットを作成する必要があります。

次の .NET プロジェクト Target ノードの例を考えてみましょう。

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

ツールが署名の過程でファイルをコピーする必要がある可能性があります。 これは、元のファイルがビルドによって所有されていない共有アイテムである場合に発生する可能性があります。たとえば、NuGet キャッシュから取得されるファイルです。 このような場合、ツールは、変更されたコピーを指すように、対応する FilesToBundle 項目のパスを変更することが予想されます。

単一ファイル アプリでアセンブリを圧縮する

埋め込みアセンブリの圧縮を有効にして単一ファイル アプリを作成できます。 EnableCompressionInSingleFile プロパティを true に設定します。 生成された単一ファイルには、すべての埋め込みアセンブリが圧縮されており、実行可能ファイルのサイズを大幅に減らすことができます。

圧縮にはパフォーマンス コストが伴います。 アプリケーションの起動時に、アセンブリをメモリに展開する必要があり、この処理に時間がかかります。 使用する前に、圧縮を有効にした場合のサイズ変更と起動コストの両方を測定することをお勧めします。 影響は、アプリケーションによって大きく異なる場合があります。

単一ファイル アプリを検査する

ILSpy ツールを使用して、1 つのファイル アプリを検査できます。 このツールでは、アプリケーションにバンドルされているすべてのファイルを表示し、マネージド アセンブリの内容を検査することができます。

関連項目