Help us understand the problem. What is going on with this article?

WPFで実行ファイルとDLLを一つにまとめる(C#編)

More than 5 years have passed since last update.

その1 プロジェクトファイルにコマンドを追加

C#プロジェクトファイルの

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets"/>

のあとに以下の文字列を挿入します

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

その2 EXEからアセンブリをロードするコードを追加

以下のコードをソースファイルにしてプロジェクトに追加してください。

startup.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;

namespace StartUpCode //名前空間は使いやすいものに変えてください
{
    public class StartUp
    {
        [STAThread]
        public static void Main()
        {
            AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly;

            App.Main(); // Run WPF startup code.
        }

        private static Assembly OnResolveAssembly(object sender, ResolveEventArgs e)
        {
            var thisAssembly = Assembly.GetExecutingAssembly();

            // Get the Name of the AssemblyFile
            var assemblyName = new AssemblyName(e.Name);
            var dllName = assemblyName.Name + ".dll";

            // Load from Embedded Resources - This function is not called if the Assembly is already
            // in the same folder as the app.
            var resources = thisAssembly.GetManifestResourceNames().Where(s => s.EndsWith(dllName));
            if (resources.Any())
            {

                // 99% of cases will only have one matching item, but if you don't,
                // you will have to change the logic to handle those cases.
                var resourceName = resources.First();
                using (var stream = thisAssembly.GetManifestResourceStream(resourceName))
                {
                    if (stream == null) return null;
                    var block = new byte[stream.Length];

                    // Safely try to load the assembly.
                    try
                    {
                        stream.Read(block, 0, block.Length);
                        return Assembly.Load(block);
                    }
                    catch (IOException)
                    {
                        return null;
                    }
                    catch (BadImageFormatException)
                    {
                        return null;
                    }
                }
            }
            // in the case the resource doesn't exist, return null.
            return null;
        }
    }
}

その3 プロジェクト設定を変更

プロジェクト設定を変更して、スタートアップオブジェクトをその2で追加したソースに変更する。
すべて終了したらビルドすればEXE単独で起動できるようになります。

ただし、WPFToolkitのグラフのようにDLLからDLLの関数を呼んでいたりすると動かない場合があるので100%とはいきませんが99%くらいはこれでいけます。

WPFプロジェクトじゃなくても使えるので意外に便利です。

今回の記事は次のサイトの日本語訳だったりする
http://blogs.interknowlogy.com/2011/07/13/merging-a-wpf-application-into-a-single-exe/

VBmouiya
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away