Right now do !

[.NET Utility] ilmerge:Assembly 병합 도구

by 지금당장해

개발 중에 이런 저런 자료를 뒤지다가 이건 꼭 나중에 한번 사용해 봐야지 하는 것들이 있는데 그중에 하나다. 드디어 오늘 사용 했다. ilmerge 제목에서도 언급 했듯이 병합 도구이다. 제품을 만들때 어셈블리가 나누어지고 모듈화를 지향 하다보면 이렇게 나누어진 상태로 배포를 하고 사용을 하는 것이 일반적이다. 그러다 너무 많아 지기도 한다. 그러다가 꼭 10번째 돼지를 잃어 버리곤 한다. 


오늘 내가 처한 상황은 이렇다. Windows service를 하나 만들었는데 Un-Handled 예외 처리가 필요 했고 이를 로깅하기 위해 회사 공통 라이브러리(log4net을 랩핑)를 하나 외부 참조하여 사용 했다. 


static void Main()
{
    AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

    ServiceBase[] ServicesToRun = null;

    try
    {                
        ServicesToRun = new ServiceBase[]
        {
            new Service()
        };
    }
    catch(Exception ex)
    {
        // 예상하지 못한 오류가 발생 한 경우를 위해 로그를 쓰는 함수를 정적 참조 하지만 결구 또 다른 오류를 유발 시킨다.
        Service.Log.WriteError(Resources.EX_MSG_ON_CREATE_SERVICE_OBJECT, ex);
    }
                

    ServiceBase.Run(ServicesToRun);
}

private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    Exception ex = e.ExceptionObject as Exception;

    // 예상하지 못한 오류가 발생 한 경우를 위해 로그를 쓰는 함수를 정적 참조 하지만 결구 또 다른 오류를 유발 시킨다.
    // 이런 성격의 어셈블리는 차라리 병합을 시켜 오류가 발생할 수 있는 가능성을 최대한 줄이기로 결정 했다.
    if (ex == null)
    {        
        Service.Log.WriteError(Resources.EX_MSG_UNHANDLED_EXCEPTION);
    }
    else
    {        
        Service.Log.WriteError(Resources.EX_MSG_UNHANDLED_EXCEPTION, ex);
    }
}


근데 여러 테스트 환경에 옮겨서 사용하는데 자꾸 이 어셈블리를 배포 해야 한다는 것을 까먹어 버린다. (물론 Package화 하고나면 크게 문제될 것은 없지만, 자 이럴때는 TypeInitializationException이 발생 한다.) 전역 오류를 잡는곳에서 또 오류를 발생 시켜버리니 확 짜증이 난다. 애라 합쳐 버리자. 사용을 결심하게 된 배경은 이렇고 뭐 다운 받아서 적용하면 되겠지라고 생각했는데 역시 첨음 해보는것은 그냥 넘어 가는 법이 없다.


Step 1. 설치


마이크로소프트 공식 다운로드를 통해 ilmerge을 다운로드 받고 설치 한다. 그러면 C:\Program Files (x86)\Microsoft\ILMerge폴더에 해당 패키지가 설치 된다. (32bit컴에서는 (x86)을 생략하면 된다.) 이 프로그램은 그냥 콘솔 프로그램이다. cmd창을 열어서 쓰면 된다. 나는 편의상 해당 경로를 환경설정에 PATH항목을 추가 하여 다른 경로에서되 불러 쓸수 있도록 했다.


Step 2. 실행


ilmerge /out:[합쳐질 파일이름].exe [병합대상어셈블리1].exe [병합대상어셈블리2].dll {[병합대상어셈블리3].dll} 


원래는 위 정도만 해도 되야 하는데 뭔가 오류가 났다.

An exception occurred during merging:

ILMerge.Merge: The assembly '병합대상어셈블리2' was not merged in correctly. It is still listed as an external reference in the target assembly.

   위치: ILMerging.ILMerge.Merge()

   위치: ILMerging.ILMerge.Main(String[] args)



구글링을 해서 자료를 찾다 보니 Stackoverflow에 아래와 같은 글이 있어 /closed를 추가 해봤다. 된다. 이유는 정확히 모르겠다. 


I had to use the /closed argument. According to the official docs:

Closed

When this is set before calling Merge, then the "transitive closure" of the input assemblies is computed and added to the list of input assemblies. An assembly is considered part of the transitive closure if it is referenced, either directly or indirectly, from one of the originally specified input assemblies and it has an external reference to one of the input assemblies, or one of the assemblies that has such a reference. Complicated, but that is life...


참고로 ilmerge에 대한 각 옵션 설명은 아래 주소를 참고 하기 바란다.

https://github.com/Microsoft/ILMerge/blob/master/ilmerge-manual.md

블로그의 정보

지금 당장 해!!!

지금당장해

활동하기