単一実行ファイルとして発行するファイルの中に含めずに個別のファイルとして発行する方法

ページ更新日 :
ページ作成日 :

環境

Visual Studio
  • Visual Studio 2019
ASP.NET Core
  • 3.1

単一ファイルとは

通常プログラムを動かすには exe ファイルの他に dll などのファイルが必要になることが多く、 プログラムの配布には複数のファイルと配布することになります。

.NET Core 3.0 から追加された機能「単一ファイル作成」を使用してプログラムを発行することにより、全てのファイルを一つの exe にまとめて実行することができるようになりました。(pdb ファイルはデバッグ情報のファイルなので配布しなくてもいいです)

しかし、場合によっては設定ファイルなどを exe の中に含めず、exe のあるフォルダに配置したい場合もあるかと思います。 ここではその方法について説明します。

単一ファイル出力の準備

サンプルとして以下のようなプロジェクト構成とし、起動時に TextFile1.txt ファイルを読み込むものとします。 TextFile1.txt は exe ファイルと一緒に配布する想定なので「ビルドアクション:なし」「出力ディレクトリにコピー:新しい場合はコピーする」にします。 TextFile1.txt の中身は任意の内容で構いません。

プログラムについては一緒に配布されているファイルを読み込むという想定でプログラムを組んでも大丈夫です。

ただし、単一ファイルにした実行ファイルは、実際には実行した際に別の一時フォルダに展開されるので、 ファイルを相対パスで読み込む際は実行ファイルのあるフォルダではなく、実行ファイルを起動したフォルダで指定する必要があります。

using System;
using System.Diagnostics;
using System.IO;

namespace ExcludeFromSingleFile
{
  class Program
  {
    static void Main(string[] args)
    {
      using var processModule = Process.GetCurrentProcess().MainModule;
      Console.WriteLine(File.ReadAllText(Path.Combine(Path.GetDirectoryName(processModule.FileName), "TextFile1.txt")));
      Console.ReadKey();
    }
  }
}

デバッグ実行するとファイルが読み込まれていることが分かります。

まだ単一ファイルには纏めていないので出力フォルダに TextFile1.txt も出力されています。

ではこの状態で単一ファイルとして発行してみます。発行の説明が目的ではないので手順は省略しています。

単一ファイルにするにはターゲット ランタイムをポータブル以外にする必要があります。

まだ何も設定していないので通常通り1ファイルになりました。

実行しても TextFile1.txt がないのでエラーになってしまいます。

単一ファイルに含めずに特定のファイルを発行する方法

単一ファイルに含めないファイルをプロジェクトに含めている状態でプロジェクトファイル(csproj)をコードで開きます。

以下のような XML になっていると思います。この中から設定を変更する対象のファイルを探します。 プロジェクトの設定によっては対象のファイルがない場合もありますので、その場合は手動で追加する必要があります。

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <None Update="TextFile1.txt">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
  </ItemGroup>
</Project>

対象のファイルを見つけたら以下のように ExcludeFromSingleFiletrue で追加します。 名前の通り単一ファイルから除外するという意味になります。

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <None Update="TextFile1.txt">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <!-- ここから追加 -->
      <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
      <!-- ここまで追加 -->
    </None>
  </ItemGroup>
</Project>

保存したら発行してみてください。単一ファイルから除外されて発行されていることが分かります。

発行されたファイルを実行しても正しく動作していることを確認できます。