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ファイルのプロジェクトへのインポート
- Visual Studioを開く
- プロジェクト内に適当なフォルダを作成(libとかResourceとか)
- フォルダを右クリック>追加>既存の項目>EXEに組み込みたいDLLをプロジェクトにインポート
- インポートしたファイル>プロパティ>ビルドアクション>「埋め込まれたリソース」に変更
③外から呼び出すAppクラスをMainを追加
- ランチャー用に空のCSファイルを追加(例:Launcher.cs)
- 以下のコードを打ち込む(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); } } }
⑤ビルド
上手くビルドできればDLLを含んだ分EXEのサイズが大きくなっていると思います。
EXEを単独でコピーしてプログラムをテストしてみて動けばOKです。