Winform/wpf 개발에서는 많은 서드파티 DLL을 언급하지만, 패키징할 때마다 디버그 디렉터리의 파일을 고객에게 복사하거나 공유해야 하므로 사용이 매우 편리하지 않습니다. 저는 ILMerge, Enigma Virtual Box 등 여러 dll 파일을 병합하는 소프트웨어를 시도해봤지만, "Costura.Fody"를 알기 전까지는 세상이 훨씬 낫다고 느꼈습니다~
다음은 Winform에서 작성한 프로그램으로, "HttpHelper.dll"와 "Newtonsoft.Json.dll"라는 두 DLL을 참조합니다. 프로그램을 생성할 때 exe 파일과 이 두 개의 DLL 파일이 있어 사용자에게 매우 불편함을 줍니다. 그리고 DLL이 하나 줄어들면 아래 그림과 같이 예외를 보고할 수 있습니다:
아래 링크는 이전 사용 방식입니다(권장하지 않음)
Costura.Fody 도구를 사용하면 소스 DLL을 대상 EXE로 병합할 수 있습니다
프로젝트 홈페이지: https://github.com/Fody/Costura
사용 방법, nuget 패키지 직접 설치:
Costura.Fody를 성공적으로 추가하면, 솔루션이 자동으로 FodyWeavers.xml 파일을 추가합니다.
해결책을 다시 생성하면 프로그램 생성 디렉터리에서 성공 사례를 확인할 수 있고, 모든 DLL이 exe에 완벽하게 병합되어 있으며, exe 파일을 클라이언트에 직접 복사해 독립적으로 실행할 수 있습니다. 아래에 나와 있습니다:
1>------ 모든 재구성이 시작되었습니다: 프로젝트: itsvse, 구성: 디버그 모든 CPU ------ 1> Fody: Fody (버전 2.0.0.0) 실행 중 1> 포디/코스투라: 'Costura.dll'에 대한 언급은 발견되지 않음. 참고문헌은 수정되지 않았습니다. 1> 포디/코스투라: 'E:\project\itsvse\itsvse\HttpHelper.dll' 내비딩. 1> 포디/코스투라: 'E:\project\itsvse\itsvse\Newtonsoft.Json.dll' 삽입 1> 포디: 포디를 609ms로 마쳤습니다. 1> 포디: 구성 시 비활성화되어 있어 어셈블리 검증을 건너뛸 수 있습니다 1> 포디: 3ms 만에 검증을 완료했습니다. 1> itsvse -> E:\project\itsvse\itsvse\bin\Debug\itsvse.exe ========== 모두 재생: 1개 성공, 0개 실패, 0개 건너뛸 ==========
위 사진에서 볼 수 있듯이, 생성된 파일에는 Newtonsoft.Json.dll, HttpHelper.dll, Costura.dll가 생성되지 않고 두 개의 itsvse.exe파일만 생성되어 오류 없이 직접 실행할 수 있습니다! (PDB 파일은 삭제할 수 있습니다.)
ILSpy 도구를 사용해 프로그램을 디컴파일하고 아래 그림에 보이는 대로 생성된 소스 코드를 살펴보겠습니다:
구현 원칙 소개
CLR이 어셈블리를 로드하려 하지만 로드에 실패하면 AppDomain.AssemblyResolve 이벤트가 발생합니다. 우리 프로그램은 이 이벤트를 감지하고 CLR이 로드하려는 어셈블리를 이벤트 핸들러에 반환하여 프로그램이 정상적으로 계속 작동할 수 있도록 합니다.
Fody.Costura는 프로젝트를 만들 때 EXE가 참조하는 모든 DLL을 EXE 파일에 임베드합니다. 프로그램이 실행 중에 이 DLL 중 하나를 사용할 때(CLR이 DLL 파일을 찾지 못해 AppDomain.AssemblyResolve 이벤트가 트리거됨), 필요한 DLL은 EXE 파일의 내장된 자원에서 추출됩니다.
Attach의 메서드가 AppDomain.AssemblyResolve 이벤트를 듣는 것을 볼 수 있습니다. CLR이 어셈블리를 성공적으로 로드하지 못하면 AssemblyResolve 이벤트 핸들러가 실행됩니다. AssemblyResolve는 Common.ReadFromEmbeddedResources 메서드를 통해 로드된 어셈블리의 내장 자원에서 대상 어셈블리를 가져오고 CLR로 반환합니다.
이런 점을 보면, Attach(첨부) 방식이 언제 도입되었는지 궁금하실 수 있습니다.
사실 C# 언어의 경우 CLR은 큰 비결을 숨깁니다 - 각 모듈(각 어셈블리는 하나 이상의 모듈로 구성됨)이 로드되기 전에 초기화된 코드를 실행할 수 있습니다. 안타깝게도 C# 언어는 이 부분을 제어할 수 없습니다. Fody.Costura는 IL 코드를 EXE 어셈블리 내부 모듈의 초기화 함수에 직접 주입하며, 이 IL 코드 부분이 실제로 Attach 메서드를 실행합니다. 이렇게 하면 EXE 어셈블리가 로드되면 즉시 Attach를 호출할 수 있습니다.
위에서는 Fody.Costura의 구현 원칙에 대한 간략한 소개입니다.
고급 구성
이러한 구성은 CosturaFodyWeavers.xml 파일에 추가되거나 수정됩니다.
임시 어셈블리 생성 기본값: false 이 방식은 메모리에 로드하기 전에 임베디드 파일을 디스크에 임베드합니다. 이 기능은 물리적 파일에서 어셈블리를 불러오고 싶은 특정 상황에서 유용합니다.
IncludeDebugSymbols 기본값: true(참) 참조 어셈블리의 .pdbs도 임베드되어 있는지 제어합니다.
디스에이블 컴프레션 기본값: false 임베디드 어셈블리는 기본적으로 압축되어 있고 로드 시 압축되지 않습니다. 이 옵션을 사용해 압축을 끌 수 있습니다. 참고: 비표준 DLL이나 암호화된 DLL을 참조할 때는 이 속성을 반드시 꺼 주세요. 그렇지 않으면 실행 파일을 열 수 없는 상황이 발생할 수 있습니다. 이 사실은 DSkin.dll를 사용할 때 발견되었습니다.
DisableCleanup 기본값: false 코스투라의 일부로서 내장 부품은 더 이상 빌드에 포함되지 않습니다. 이 정리는 끌 수 있습니다.
로드앳모듈Init 기본값: true(참) 코스투라는 모듈 초기화 시 기본적으로 로드됩니다. 플래그가 행동을 비활성화합니다. CosturaUtility.Initialize() 어딘가에 사용할 수 있는지 확인하세요.
어셈블리 제외 사용법: ExcludeAssemblies="DLL1| DLL2" 기본 동작인 "모든 복사 로컬 참조를 삽입"에서 제외할 어셈블리 이름 목록입니다.
어셈블리 포함 사용 방법: IncludeAssemblies="DLL1| DLL2" 기본 동작인 '모든 로컬 참조를 삽입하기'에 포함된 어셈블리 이름 목록입니다.
Unmanaged32Assemblies&Unmanaged64Assemblies 사용 방법: Unmanaged32Assemblies="DLL1| DLL2" Unmanaged64Assemblies="DLL1| DLL2" 혼합 모드 어셈블리는 관리되는 어셈블리와 같은 방식으로 로드할 수 없습니다. 따라서 코스투라가 혼합 모드에 있는 구성 요소를 식별하고 어떤 환경에서 로드할지 식별하는 데 도움이 되도록, 이들의 이름은 한쪽 또는 두 가지 목록에 포함되어야 합니다. 이름에 .exe나 .dll를 포함하지 마세요.
프리로드 오더 사용: PreloadOrder="DLL1| DLL2" 지역 도서관은 Costura에서 자동으로 로드할 수 있습니다. 로컬 라이브러리를 포함하려면, 라이브러리의 불안정성에 따라 costura32 또는 costura64라는 폴더라는 임베디드 리소스로 프로젝트 내에 포함하세요. 또는 미리 로드된 라이브러리를 로드하는 순서를 지정할 수도 있습니다. 디스크에서 임시 컴포넌트를 섞을 때도 미리 로드되어 있습니다.
코스투라유틸리티 사용 방법:
CosturaUtility는 자신의 코드로 Costura 시스템을 수동으로 초기화할 수 있게 해주는 클래스입니다.이는 주로 모듈 초기화 프로그램이 작동하지 않는 상황을 위한 것입니다라이브러리와 모노 같은 경우입니다.
마지막으로, 텍스트에 있는 소스 코드를 다운로드하세요:
관광객 여러분, 이 게시물의 숨겨진 내용을 보고 싶으시다면 부탁드립니다 회답
|