하나의 dll을 다른 내부에 포함 된 리소스로 포함하고 내 코드에서 호출
다른 타사 DLL을 사용하는 DLL이 있지만 가능한 경우 둘 다 함께 유지하는 대신 타사 DLL을 DLL로 빌드 할 수있는 상황이 있습니다.
이것은 C # 및 .NET 3.5입니다.
이 작업을 수행하는 방법은 타사 DLL을 포함 된 리소스로 저장 한 다음 첫 번째 DLL을 실행하는 동안 적절한 위치에 배치하는 것입니다.
처음에이 작업을 계획 한 방법 System.Reflection.Assembly.GetExecutingAssembly().Location.ToString()
은 마지막 .NET Framework에서 지정한 위치에 타사 DLL을 배치하는 코드를 작성하는 것 /nameOfMyAssembly.dll
입니다. .DLL
이 위치에 제 3자를 성공적으로 저장할 수 있습니다.
C : \ Documents and Settings \ myUserName \ Local Settings \ Application Data \ assembly \ dl3 \ KXPPAX6Y.ZCY \ A1MZ1499.1TR \ e0115d44 \ 91bb86eb_fe18c901
), 그러나이 DLL이 필요한 코드 부분에 도달하면 찾을 수 없습니다.
내가 다르게해야 할 일에 대해 아는 사람이 있습니까?
타사 어셈블리를 리소스로 포함했으면 AppDomain.AssemblyResolve
응용 프로그램 시작 중에 현재 도메인 의 이벤트 를 구독하는 코드를 추가 합니다. 이 이벤트는 CLR의 Fusion 하위 시스템이 유효한 프로빙 (정책)에 따라 어셈블리를 찾지 못할 때마다 발생합니다. 에 대한 이벤트 처리기에서 AppDomain.AssemblyResolve
를 사용하여 리소스를로드하고 Assembly.GetManifestResourceStream
해당 콘텐츠를 해당 Assembly.Load
오버로드에 바이트 배열로 공급합니다 . 다음은 이러한 구현이 C #에서 어떻게 보일 수 있는지입니다.
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
var resName = args.Name + ".dll";
var thisAssembly = Assembly.GetExecutingAssembly();
using (var input = thisAssembly.GetManifestResourceStream(resName))
{
return input != null
? Assembly.Load(StreamToBytes(input))
: null;
}
};
곳은 StreamToBytes
로 정의 할 수 있습니다 :
static byte[] StreamToBytes(Stream input)
{
var capacity = input.CanSeek ? (int) input.Length : 0;
using (var output = new MemoryStream(capacity))
{
int readLength;
var buffer = new byte[4096];
do
{
readLength = input.Read(buffer, 0, buffer.Length);
output.Write(buffer, 0, readLength);
}
while (readLength != 0);
return output.ToArray();
}
}
마지막으로, 이미 언급했듯이 ILMerge 는 다소 복잡하지만 고려할 수있는 또 다른 옵션이 될 수 있습니다.
결국 나는 raboof가 제안한 방식 (그리고 dgvid가 제안한 것과 유사 함)을 거의 정확하게했지만 약간의 변경과 일부 누락이 수정되었습니다. 이 방법은 처음에 내가 찾고 있던 것과 가장 가깝고 타사 실행 파일 등을 사용할 필요가 없었기 때문에 선택했습니다. 잘 작동합니다!
내 코드는 다음과 같습니다.
편집 : 여러 파일에서 재사용 할 수 있도록이 함수를 다른 어셈블리로 이동하기로 결정했습니다 (Assembly.GetExecutingAssembly ()를 전달합니다).
이것은 임베디드 dll이있는 어셈블리를 전달할 수있는 업데이트 된 버전입니다.
embedResourcePrefix는 포함 된 리소스에 대한 문자열 경로이며 일반적으로 리소스를 포함하는 폴더 구조가 뒤에 오는 어셈블리 이름입니다 (예 : dll이 프로젝트의 Resources라는 폴더에있는 경우 "MyComapny.MyProduct.MyAssembly.Resources"). ). 또한 dll에 .dll.resource 확장자가 있다고 가정합니다.
public static void EnableDynamicLoadingForDlls(Assembly assemblyToLoadFrom, string embeddedResourcePrefix) {
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => { // had to add =>
try {
string resName = embeddedResourcePrefix + "." + args.Name.Split(',')[0] + ".dll.resource";
using (Stream input = assemblyToLoadFrom.GetManifestResourceStream(resName)) {
return input != null
? Assembly.Load(StreamToBytes(input))
: null;
}
} catch (Exception ex) {
_log.Error("Error dynamically loading dll: " + args.Name, ex);
return null;
}
}; // Had to add colon
}
private static byte[] StreamToBytes(Stream input) {
int capacity = input.CanSeek ? (int)input.Length : 0;
using (MemoryStream output = new MemoryStream(capacity)) {
int readLength;
byte[] buffer = new byte[4096];
do {
readLength = input.Read(buffer, 0, buffer.Length); // had to change to buffer.Length
output.Write(buffer, 0, readLength);
}
while (readLength != 0);
return output.ToArray();
}
}
이를 수행 할 수있는 IlMerge라는 도구가 있습니다. http://research.microsoft.com/~mbarnett/ILMerge.aspx
그런 다음 다음과 유사한 빌드 이벤트를 만들 수 있습니다.
Path = "C : \ Program Files \ Microsoft \ ILMerge"설정
ilmerge /out:$(ProjectDir)\Deploy\LevelEditor.exe $ (ProjectDir) \ bin \ Release \ release.exe $ (ProjectDir) \ bin \ Release \ InteractLib.dll $ (ProjectDir) \ bin \ Release \ SpriteLib.dll $ (ProjectDir) \ bin \ Release \ LevelLibrary.dll
I've had success doing what you are describing, but because the third-party DLL is also a .NET assembly, I never write it out to disk, I just load it from memory.
I get the embedded resource assembly as a byte array like so:
Assembly resAssembly = Assembly.LoadFile(assemblyPathName);
byte[] assemblyData;
using (Stream stream = resAssembly.GetManifestResourceStream(resourceName))
{
assemblyData = ReadBytesFromStream(stream);
stream.Close();
}
Then I load the data with Assembly.Load().
Finally, I add a handler to AppDomain.CurrentDomain.AssemblyResolve to return my loaded assembly when the type loader looks it.
See the .NET Fusion Workshop for additional details.
You can achieve this remarkably easily using Netz, a .net NET Executables Compressor & Packer.
Instead of writing the assembly to disk you can try to do Assembly.Load(byte[] rawAssembly) where you create rawAssembly from the embedded resource.
ReferenceURL : https://stackoverflow.com/questions/96732/embedding-one-dll-inside-another-as-an-embedded-resource-and-then-calling-it-fro
'Development Tip' 카테고리의 다른 글
find 명령의 -exec 옵션에 백 슬래시와 세미콜론이 필요한 이유는 무엇입니까? (0) | 2020.12.30 |
---|---|
동일한 기능에서 반환 및 산출 (0) | 2020.12.30 |
날짜 범위별로 Subversion 저장소에서 변경 사항 목록을 어떻게 얻습니까? (0) | 2020.12.30 |
열거 형을 배열 인덱스로 사용 (0) | 2020.12.30 |
Scala의 기능적 반응 형 프로그래밍 (0) | 2020.12.30 |