NGMsoftware

NGMsoftware
로그인 회원가입
  • 매뉴얼
  • 팁 앤 테크
  • 매뉴얼

    팁과 테크니컬 노하우를 확인하세요.

    팁 앤 테크

    팁과 테크니컬 노하우를 확인하세요.

    본 사이트의 컨텐츠는 저작권법의 보호를 받으므로 무단 복사, 게재, 배포 등을 금합니다.

    디자이너 여러개의 dll을 묶어서 하나의 exe로 배포하기. (Packing)

    페이지 정보

    본문

    안녕하세요. 소심비형입니다. 커스텀 모듈 또는 디자이너에서 복잡한 작업 또는 외부 라이브러리를 붙여서 사용한다면 배포할 때 추가된 라이브러리도 모두 배포해야 합니다. 배포 프로세스가 있거나 Installer와 같은 툴이 있으면 큰 문제는 없지만, 직접 압축해서 전달해야 한다면 문제가 될수도 있죠. 관리측면에서 그렇다는 의미입니다. 그래서, 오늘은 작은(?) 응용 프로그램을 좀 더 쉽게 배포할 수 있는 방법에 대해 알아보겠습니다. 예를들면, 1MB도 안되는 용량에 exe 하나와 여러개의 lib을 가지면 배포하기가 여간 귀찮은게 아닙니다-_-; 해당 폴더를 압축해서 공유한다던가 포함된 모든 파일을 개별적으로 전달해야 하는 번거로움(?)이 발생하죠. 물론, 관리 측면에서는 원본 그대로 배포하는게 유리합니다.

    img.jpg

     

     

    아래 그림은 이미 만들어진 프로그램의 목록입니다. 이 프로그램은 Miracom에서 개발한 Message bus middleware입니다. 지금은 삼성 계열사인데요. Tibrv를 사용할바엔 미라콤의 하이웨이101을 쓰는게 좋을거 같아요. 국산이어서가 아니라 사용법도 쉽고 성능(1분당 메시지 전송량)도 뒤쳐지지 않기 때문입니다. 여하튼, 팁코는 RVP(Rendezvous Protocol)를 사용하고 미라콤은 UDP(User Datagram Protocol)를 사용합니다.

    (나중에 Linux계열 서버에 설치할 때 방화벽은 UDP를 열어야 합니다.)

    img.png

     

     

    이 그림에서 Highway101Client는 윈폼으로 exe입니다. 따라서, main을 가지고 있죠. 이외에 AbstractTransfer, CasterRequestReply, CasterSendGunicast등등은 dll입니다. 이 프로그램을 빌드한 후 배포한다면 한개의 exe와 10개의 dll을 같이 배포해야 합니다. 그렇지 않다면 dll을 찾지 못해서 에러가 발생하게 됩니다. 아무튼, 용량의 압박이 없다면 배포의 편의성을 위해 Highway101Client에 나머지 라이브러리들을 Embedded Resources(포함 리소스)로 한번에 배포하는게 좋습니다. Highway101Client의 프로젝트 속성에서 리소스 탭으로 이동합니다. dll은 리소스로 직접 추가할 수 없기 때문에 이미지 아무거나 하나 추가한 후 솔루션 탐색기에 생성된 Resources폴더에 직접 라이브러리들을 추가해야 합니다.

    img.png

     

     

    배포해야 할 라이브러리들을 리소스에 모두 추가했다면 아래 그림처럼 "포함 리소스"로 변경하세요.

    img.png

     

     

    프로그램의 진입점(main)에서 아래와 같이 이벤트와 코드를 추가하세요.

    Program.cs

    using System;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Windows.Forms;
    namespace Highway101Client
    {
        static class Program
        {       
            /// <summary>        
            /// 해당 응용 프로그램의 주 진입점입니다.        
            /// </summary>        
            [STAThread]
            static void Main()
            {
                AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(ResolveAssembly);
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
            static Assembly ResolveAssembly(object sender, ResolveEventArgs args)
            {
                Assembly thisAssembly = Assembly.GetExecutingAssembly();
                string fileName = args.Name.Substring(0, args.Name.IndexOf(',')) + ".dll";
                string resourceName = null;
                if (thisAssembly.ImageRuntimeVersion.Contains("v4"))
                {
                    var resources = thisAssembly.GetManifestResourceNames().Where(s => s.EndsWith(fileName));
                    if (resources.Count() > 0)
                    {
                        resourceName = resources.First();
                        using (Stream stream = thisAssembly.GetManifestResourceStream(resourceName))
                        {
                            if (stream != null)
                            {
                                byte[] assembly = new byte[stream.Length];
                                stream.Read(assembly, 0, assembly.Length);
                                return Assembly.Load(assembly);
                            }
                        }
                    }
                }
                else
                {
                    foreach (string name in thisAssembly.GetManifestResourceNames())
                    {
                        if (name.EndsWith(fileName))
                        {
                            resourceName = name;
                            break;
                        }
                    }
                    if (resourceName != null)
                    {
                        using (Stream stream = thisAssembly.GetManifestResourceStream(resourceName))
                        {
                            if (stream != null)
                            {
                                byte[] assembly = new byte[stream.Length];
                                stream.Read(assembly, 0, assembly.Length);
                                return Assembly.Load(assembly);
                            }
                        }
                    }
                }
                return null;
            }
        }
    }

     

     

    18라인은 이 응용 프로그램이 실행되는 도메인에서 참조된 라이브러리를 찾을 수 없을 때 이벤트를 발생시킵니다. 우리가 exe만 배포했기 때문에 이 이벤트에 연결된 메소드가 실행됩니다. 31라인에서 .NET Framework의 버전이 4이상이면 람다식을 이용하여 리소스에 추가한 라이브러리를 찾습니다. 뭐 코드에 큰 차이는 없기 때문에 분기되는 로직은 삭제해도 문제되지 않습니다.

    img.jpg

    • 네이버 공유하기
    • 페이스북 공유하기
    • 트위터 공유하기
    • 카카오스토리 공유하기
    추천1 비추천0

    댓글목록

    등록된 댓글이 없습니다.