C#でシングルバイナリでビルドすると.exeファイルのサイズが巨大になる。

コンピュータ

C# の .NET 6/7/8 以降では、dotnet publish コマンドで単一ファイル(シングルバイナリ)として .exe を出力することができます。
ただし、そのままでは 実行ファイルのサイズが非常に大きく なります。

ビルドコマンド

dotnet publish -r win-x64 -c Release /p:PublishSingleFile=true /p:IncludeAllContentForSelfExtract=true /p:SelfContained=true --output ./output

結果

    Directory: H:\csharp\console\SingleBinary01\output

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---          2025/07/30    10:21       67548742 SingleBinary01.exe
-a---          2025/07/30    10:21          10532 SingleBinary01.pdb

圧縮するオプション
ファイル名:SingleBinary01.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    
    <EnableCompressionInSingleFile>true</EnableCompressionInSingleFile>
  </PropertyGroup>

</Project>

結果

    Directory: H:\csharp\console\SingleBinary01\output

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---          2025/07/30    10:27       35164192 SingleBinary01.exe
-a---          2025/07/30    10:27          10532 SingleBinary01.pdb

52%ぐらいに圧縮された。(67MB → 35MB)

念のため実行

 ./output/SingleBinary01.exe
Hello, World!

WPFのGUIアプリだとどれだけのサイズになるか気になるので試してみました。
基本的にプロジェクトはConsoleのままコードを以下の様に変更しました。

ファイル名:SingleBinary01.csproj


<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0-windows</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <UseWPF>true</UseWPF>
    <StartUP>SingleBinary01.App</StartUP>
    <EnableCompressionInSingleFile>true</EnableCompressionInSingleFile>
  </PropertyGroup>

</Project>

ファイル名:App.xaml.cs


using System.Windows;

namespace SingleBinary01;

public partial class App : Application
{
    [STAThread]
    public static void Main()
    {
        var app = new App();
        var window = new MainWindow();
        app.Run(window);
    }
}

ファイル名:MainWindow.xaml.cs


using System.Windows;

namespace SingleBinary01;
public partial class MainWindow : Window
{
    public MainWindow()
    {
        Title = "シングルバイナリ";
        Width = 800;
        Height = 150;
    }
}

実行すると空のウィンドウが表示されました。

ファイルサイズを確認します。

    Directory: H:\csharp\console\SingleBinary01\output

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---          2025/07/30    10:40       71701074 SingleBinary01.exe
-a---          2025/07/30    10:40          12580 SingleBinary01.pdb

コンソール(圧縮)で37MBがWPUのGUI(圧縮)で72MBと大きくは成りましたが、思ったほどではございませんでした。

コンソールアプリで37MBは正直どうかと思いますが、GUIアプリで71MBなら配布を検討しても良いサイズだと思います。

思い付きで、WPFアプリを自己完結型のシングルバイナリを作成してみましたが、Microsoftの公式ドキュメントでもあまり触れられていません。本来はCLI向けの用途が想定されている機能ですが、WPFでも意外に実用になることが確認できました。
ただし、一時ファイルの展開や起動時間など、細かな挙動には注意が必要かもしれません。

シングルバイナリのメリットは、実行環境に.NETのランタイムのインストールが不要である点があげられます。実行に必要な.NETのランタイムライブラリを埋め込んで、数十MBで済んでいる考えると、十分コンパクトだと言えるかもしれませんね。

コメント

  1. sheephuman より:

    WPFは色々作りこんだら200MBぐらいになったんで、実はそうでもないと思いますけどね。