포함 한 dll 내부에 또 다른 포함 리소스로 다음에서 호출 내 코드
문제
나는 상황이 나는 DLL 내가 만드는 사용하는 또 다른 세 번째 파티 DLL,그러나 내가 선호하는 것을 구축 할 수 있는 타사 DLL 내 DLL 하는 대신 그들을 모두 함께 가능한 경우.
이것은 C#다.NET3.5.
방법은 내가 하고 싶은 것이 저장함으로써 타사 DLL 포함 리소스로 나는 그 장소에서 적절한 위치를 실행하는 동안 첫 번째 DLL.
방법은 내가 원래 계획이지만 코드를 작성하는 방식으로 넣는 타사 DLL 에서 지정한 위치에 배치 System.Reflection.Assembly.GetExecutingAssembly().Location.ToString()
마이너스 마 /nameOfMyAssembly.dll
.나는 성공적으로 저장하 제삼자 .DLL
이 위치에서(종료되고
C:\Documents and Settings\myUserName\Local Settings\Application 데이터\assembly\dl3\KXPPAX6Y.ZCY\A1MZ1499.1TR\e0115d44\91bb86eb_fe18c901
어),하지만 때 나는 부분의 코드를 필요로 하는 DLL,그것은 그것을 찾을 수 없습니다.
누군가가 어떤 생각을 내가 무슨 일을 해야 하나요?
해결책
일단 당신이 포함된 타사 어셈블리의 자원으로,추가 코드에 구독 AppDomain.AssemblyResolve
이벤트는 현재 동안 도메인 응용 프로그램을 시작했다.이 이벤트가 발생 할 때마다는 퓨전 서브시스템의 CLR 을 찾지 못하는 어셈블리에 따라 프로빙(정책)에 효과가 있다.이벤트 처리기에 대한 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)제안하는 경우를 제외하고,일부는 사소한 변경 내용과 일부 생략 수정했습니다.이 방법이기 때문에 그것은 가장 가까운 내가 무엇을 찾고 있었는 첫 번째 장소에서 요구하지 않를 사용하여 어떠한 제삼자 실행파일과 같은.그것은 좋은 작품!
이것은 무엇을 내 코드는 끝났다고 다음과 같:
편집:나는 이동하기로 결정 이 기능은 다른 어셈블리에서 재사용 그것은 여러 파일에(난 그냥 통과에 어셈블리입니다.GetExecutingAssembly()).
이것은 버전을 업데이트할 수 있는 전달에서 어셈블리를 포함한 dll.
embeddedResourcePrefix 은 문자열한 경로를 포함 리소스,그것은 일반적으로 어셈블리의 이름 뒤에는 폴더 구조를 포함하는 리소스(예:"MyComapny.MyProduct.MyAssembly.자원인 경우"dll 라는 폴더에 리소스 프로젝트에서).그것은 또한에서는 응용 프로그램이다.dll.자원장.
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
당신은 쉽게 확인할 수 있는 이벤트 작성과 유사한 다음과 같습니다.
Set Path="C:\Program Files\Microsoft\ILMerge"
ilmerge/아웃:$(ProjectDir)\Deploy\LevelEditor.exe $(ProjectDir)\bin elease elease.exe $(ProjectDir)\bin elease\InteractLib.dll $(ProjectDir)\bin elease\SpriteLib.dll $(ProjectDir)\bin elease\LevelLibrary.dll
나는 성공이 무슨 일을 묘사하는,그러나기 때문에 제삼자 DLL 도.NET 어셈블리,내가 결코 그것을 밖으로 작성하여 디스크에,나는 그냥로드 메모리에서.
나 임베디드 리소스 어셈블리 바이트 배열로 다음과 같이
Assembly resAssembly = Assembly.LoadFile(assemblyPathName);
byte[] assemblyData;
using (Stream stream = resAssembly.GetManifestResourceStream(resourceName))
{
assemblyData = ReadBytesFromStream(stream);
stream.Close();
}
그때 나는 로드 데이터와 어셈블리입니다.부하().
마지막으로,나는 핸들러를 추가하지는 않.CurrentDomain.종속 항목을 반환하는데 로드 어셈블리는 경우 형식 로더 모니다.
보 .NET 융합 워크샵 자세한 내용은.
이를 달성할 수 있습이 매우 쉽게 사용 Netz, 다.net 순 실행 파일의 압축기&Packer.
를 쓰는 대신에,어셈블리하는 디스크 당신이 시도 할 수있는 어셈블리입니다.드(byte[]rawAssembly)을 만드는 곳 rawAssembly 에서는 임베디드 리소스입니다.