티스토리 뷰

C#

C#: dll을 포함한 단일 exe배포 방법

개태형님 2016. 10. 6. 10:10

일반적으로 프로그램을 배포시 exe파일과 Application이 호출하는 dll파일은 동일한 폴더(또는 dll 파일이 System폴더에 위치)에 있어야 한다.

 

Microsoft 공식 배포처에서는 exe와 호출하는 라이브러리를 병합하는 프로그램을 배포중이지만, 컴파일러단에서 자체 해결할 수 있는 방법도 존재한다.

 

 

1. 사용하고자 하는 dll을 프로젝트에 참조

2. 해당 dll을 프로젝트 리소스에 추가

3. 리소스에 추가된 dll의 속성 -> 빌드작업 속성 값을 포함 리소스로 지정

4. 프로그램 진입점(Program.cs)에 코드를 아래와 같이 변경

    /// <summary>
    /// 해당 응용 프로그램의 주 진입점입니다.
    /// </summary>
    [STAThread]
    static void Main()
    {
        // 리소스 dll 취득
        AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(ResolveAssembly);

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

    // .NET 4.0 이상
    static Assembly ResolveAssembly(object sender, ResolveEventArgs args)
    {
        Assembly thisAssembly = Assembly.GetExecutingAssembly();
        var name = args.Name.Substring(0, args.Name.IndexOf(',')) + ".dll";

        var resources = thisAssembly.GetManifestResourceNames().Where(s => s.EndsWith(name));
        if (resources.Count() > 0)
        {
            string resourceName = resources.First();
            using (Stream stream = thisAssembly.GetManifestResourceStream(resourceName))
            {
                if (stream != null)
                {
                    byte[] assembly = new byte[stream.Length];
                    stream.Read(assembly, 0, assembly.Length);
                    Console.WriteLine("Dll file load : " + resourceName);
                    return Assembly.Load(assembly);
                }
            }
        }
        return null;
    }

    // LINQ가 지원되지 않는 .NET 버전
    static Assembly ResolveAssembly(object sender, ResolveEventArgs args)
    {
        Assembly thisAssembly = Assembly.GetExecutingAssembly();
        string resourceName = null;
        string fileName = args.Name.Substring(0, args.Name.IndexOf(',')) + ".dll";
        foreach (string name in thisAssembly.GetManifestResourceNames())
        {
            if (name.EndsWith(fileName))
            {
                resourceName = name;
            }
        }

        if (resourceName != null)
        {
            using (Stream stream = thisAssembly.GetManifestResourceStream(resourceName))
            {
                if (stream != null)
                {
                    byte[] assembly = new byte[stream.Length];
                    stream.Read(assembly, 0, assembly.Length);
                    Console.WriteLine("Dll file load : " + resourceName);
                    return Assembly.Load(assembly);
                }
            }
        }
        return null;
    }

 

댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday