読者です 読者をやめる 読者になる 読者になる

WPFでEXEやDLLを1つのEXEファイルにマージ

Visual Studio C Sharp

WPFでアプリケーションを一つのEXEファイルに纏めたいと思ったのですが、WPFではこういう場面に使えていたILMergeが使えないようです。


代わりの手順が以下のページにありましたので、作業メモを残しておきます。
Combining multiple assemblies into a single EXE for a WPF application | DigitallyCreated



①プロジェクトファイルの編集

xxxxxx.csprojをテキストエディタで開き以下の要素を追記

<Target Name="AfterResolveReferences">
  <ItemGroup>
    <EmbeddedResource Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'">
      <LogicalName>%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)</LogicalName>
    </EmbeddedResource>
  </ItemGroup>
</Target>



②DLLファイルのプロジェクトへのインポート

  1. Visual Studioを開く
  2. プロジェクト内に適当なフォルダを作成(libとかResourceとか)
  3. フォルダを右クリック>追加>既存の項目>EXEに組み込みたいDLLをプロジェクトにインポート
  4. インポートしたファイル>プロパティ>ビルドアクション>「埋め込まれたリソース」に変更

③外から呼び出すAppクラスをMainを追加

  1. ランチャー用に空のCSファイルを追加(例:Launcher.cs)
  2. 以下のコードを打ち込む(Launcherクラスとした場合の例)
public class Launcher
{
    [STAThreadAttribute]
    public static void Main()
    {
        AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly;
        App.Main();
    }

    private static Assembly OnResolveAssembly(object sender, ResolveEventArgs args)
    {
        Assembly executingAssembly = Assembly.GetExecutingAssembly();
        AssemblyName assemblyName = new AssemblyName(args.Name);

        string path = assemblyName.Name + ".dll";
        if (assemblyName.CultureInfo.Equals(CultureInfo.InvariantCulture) == false)
        {
            path = String.Format(@"{0}\{1}", assemblyName.CultureInfo, path);
        }

        using (Stream stream = executingAssembly.GetManifestResourceStream(path))
        {
            if (stream == null)
                return null;

            byte[] assemblyRawBytes = new byte[stream.Length];
            stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length);
            return Assembly.Load(assemblyRawBytes);
        }
    }
}


④スタートアッププロジェクトの切り替え

  1. プロジェクト>右クリック>プロパティ>アプリケーション>スタートアップオブジェクト
  2. ③の手順で作成したクラスに変更




⑤ビルド

上手くビルドできればDLLを含んだ分EXEのサイズが大きくなっていると思います。
EXEを単独でコピーしてプログラムをテストしてみて動けばOKです。