포함 한 dll 내부에 또 다른 포함 리소스로 다음에서 호출 내 코드

StackOverflow https://stackoverflow.com/questions/96732

  •  01-07-2019
  •  | 
  •  

문제

나는 상황이 나는 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 에서는 임베디드 리소스입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top