[c#] 컴파일 된 실행 파일에 DLL 포함


Answers

실제로 관리되는 어셈블리 인 경우 ILMerge 를 사용할 수 있습니다. 네이티브 DLL의 경우, 할 일이 조금 더 필요합니다.

참고 항목 : C ++ windows dll을 C # 응용 프로그램 exe에 병합하려면 어떻게해야합니까?

Question

알다시피, 나는 이것에 대해 좋은 대답을 보지 못했다. 기존 DLL을 컴파일 된 C # 실행 파일에 임베드하여 (배포 할 파일이 하나 뿐이므로) 가능합니까? 가능하다면 어떻게 할 것인가?

일반적으로 DLL을 외부에두고 설치 프로그램에서 모든 것을 처리하는 것은 멋지지만, 직장에 나와이 질문을 한 사람이 몇 명 있으며 솔직히 모르겠습니다.




Jeffrey Richter발췌문 은 매우 훌륭합니다. 요컨대, 라이브러리의 임베디드 리소스를 추가하고 콜백을 추가합니다. 다음은 콘솔 앱의 Main 메소드의 시작 부분에 넣은 코드의 코드입니다 (페이지의 주석에서 찾을 수 있습니다). 라이브러리를 사용하는 모든 호출이 Main과 다른 메소드에 있는지 확인하십시오.

AppDomain.CurrentDomain.AssemblyResolve += (sender, bargs) =>
        {
            String dllName = new AssemblyName(bargs.Name).Name + ".dll";
            var assem = Assembly.GetExecutingAssembly();
            String resourceName = assem.GetManifestResourceNames().FirstOrDefault(rn => rn.EndsWith(dllName));
            if (resourceName == null) return null; // Not found, maybe another handler will find it
            using (var stream = assem.GetManifestResourceStream(resourceName))
            {
                Byte[] assemblyData = new Byte[stream.Length];
                stream.Read(assemblyData, 0, assemblyData.Length);
                return Assembly.Load(assemblyData);
            }
        };



확인란을 선택하십시오

그것은 어떤 애플 리케이션에 DLL을 포함시킬 수 있습니다. 물론 C #으로도 쓰여졌습니다. :)

희망이 도움이됩니다.




ILMerge 외에도 명령 줄 스위치를 사용하지 않으려면 ILMerge-Gui 것이 좋습니다. 그것은 오픈 소스 프로젝트입니다. 정말 좋습니다!




.vbs 스크립트에서 호출 된 csc.exe 컴파일러를 사용합니다.

xyz.cs 스크립트에서 지시문 뒤에 다음 행을 추가합니다 (본 예제는 Renci SSH).

using System;
using Renci;//FOR THE SSH
using System.Net;//FOR THE ADDRESS TRANSLATION
using System.Reflection;//FOR THE Assembly

//+ref>"C:\Program Files (x86)\Microsoft\ILMerge\Renci.SshNet.dll"
//+res>"C:\Program Files (x86)\Microsoft\ILMerge\Renci.SshNet.dll"
//+ico>"C:\Program Files (x86)\Microsoft CAPICOM 2.1.0.2 SDK\Samples\c_sharp\xmldsig\resources\Traffic.ico"

ref, res 및 ico 태그는 아래의 .vbs 스크립트에 의해 선택되어 csc 명령을 형성합니다.

그런 다음 Main에 어셈블리 확인자 호출자를 추가합니다.

public static void Main(string[] args)
{
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
    .

... 그리고 클래스의 어딘가에 리졸버 자체를 추가하십시오 :

    static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        String resourceName = new AssemblyName(args.Name).Name + ".dll";

        using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
        {
            Byte[] assemblyData = new Byte[stream.Length];
            stream.Read(assemblyData, 0, assemblyData.Length);
            return Assembly.Load(assemblyData);
        }

    }

나는 .cs 파일 이름과 일치하도록 vbs 스크립트의 이름을 지정합니다 (예 : ssh.vbs는 ssh.cs를 찾습니다). 이렇게하면 스크립트를 여러 번 쉽게 실행할 수 있지만, 저처럼 바보가 아니라면 일반 스크립트는 끌어서 놓기에서 대상 .cs 파일을 선택할 수 있습니다.

    Dim name_,oShell,fso
    Set oShell = CreateObject("Shell.Application")
    Set fso = CreateObject("Scripting.fileSystemObject")

    'TAKE THE VBS SCRIPT NAME AS THE TARGET FILE NAME
    '################################################
    name_ = Split(wscript.ScriptName, ".")(0)

    'GET THE EXTERNAL DLL's AND ICON NAMES FROM THE .CS FILE
    '#######################################################
    Const OPEN_FILE_FOR_READING = 1
    Set objInputFile = fso.OpenTextFile(name_ & ".cs", 1)

    'READ EVERYTHING INTO AN ARRAY
    '#############################
    inputData = Split(objInputFile.ReadAll, vbNewline)

    For each strData In inputData

        if left(strData,7)="//+ref>" then 
            csc_references = csc_references & " /reference:" &         trim(replace(strData,"//+ref>","")) & " "
        end if

        if left(strData,7)="//+res>" then 
            csc_resources = csc_resources & " /resource:" & trim(replace(strData,"//+res>","")) & " "
        end if

        if left(strData,7)="//+ico>" then 
            csc_icon = " /win32icon:" & trim(replace(strData,"//+ico>","")) & " "
        end if
    Next

    objInputFile.Close


    'COMPILE THE FILE
    '################
    oShell.ShellExecute "c:\windows\microsoft.net\framework\v3.5\csc.exe", "/warn:1 /target:exe " & csc_references & csc_resources & csc_icon & " " & name_ & ".cs", "", "runas", 2


    WScript.Quit(0)



일반적으로 설명하는 것처럼 어셈블리 병합을 수행하기위한 몇 가지 형태의 게시 빌드 도구가 필요합니다. Eazfuscator (eazfuscator.blogspot.com/)라는 무료 도구가 있는데, 이는 어셈블리 병합을 처리하는 바이트 코드 맹 글링을 위해 설계되었습니다. 이것을 Visual Studio의 게시 빌드 명령 줄에 추가하여 어셈블리를 병합 할 수 있지만, 비평 리 어셈블리 병합 시나리오에서 발생할 수있는 문제로 인해 마일리지가 달라질 수 있습니다.

빌드가 불안정한 지 확인하기 위해 NANT가 빌드 후에 어셈블리를 병합하는 기능을 가지고 있지만 기능이 내장되어 있는지 여부를 NANT와 친숙하지는 않습니다.

또한 응용 프로그램 빌드의 일부로 어셈블리 병합을 수행하는 많은 Visual Studio 플러그인이 있습니다.

또는 자동으로 수행 할 필요가없는 경우 .net 어셈블리를 단일 파일로 병합하는 ILMerge와 같은 여러 도구가 있습니다.

어셈블리를 병합 할 때 가장 큰 문제는 비슷한 네임 스페이스를 사용하는 경우입니다. 또는 더 나쁜, 동일한 DLL의 다른 버전을 참조하십시오 (내 문제는 일반적으로 NUnit dll 파일과 함께).







이것을 우아하게 처리 할 수있는 또 다른 제품은 SmartAssembly입니다 ( SmartAssembly.com . 이 제품은 모든 종속성을 단일 DLL로 병합하는 것 외에도 (선택적으로) 코드를 난독 화하고, 여분의 메타 데이터를 제거하여 결과 파일 크기를 줄이며, IL을 실제로 최적화하여 런타임 성능을 향상시킬 수 있습니다. 거기에는 일종의 전역 예외 처리 /보고 기능이있어 소프트웨어에 추가하여 (필요한 경우) 이해할 시간이 없지만 유용 할 수 있습니다. 또한 빌드 프로세스의 일부로 만들 수 있도록 명령 줄 API도 있다고 생각합니다.




예, .NET 실행 파일을 라이브러리와 병합 할 수 있습니다. 작업을 완료하는 데 사용할 수있는 여러 가지 도구가 있습니다.

  • ILMerge 는 여러 .NET 어셈블리를 단일 어셈블리로 병합하는 데 사용할 수있는 유틸리티입니다.
  • Mono mkbundle은 libmono 를 사용하여 exe와 모든 어셈블리를 단일 바이너리 패키지로 패키징합니다.
  • IL-Repack 은 ILMerge를 대체 할 수있는 몇 가지 추가 기능을 갖춘 FLOSS입니다.

또한 Mono Linker 와 결합하여 사용하지 않는 코드를 제거하므로 결과 어셈블리를 더 작게 만들 수 있습니다.

또 다른 가능성은 어셈블리의 압축을 허용 할뿐만 아니라 dll을 직접 exe에 압축 할 수있는 .NETZ 를 사용하는 것입니다. 위에서 언급 한 솔루션과의 차이점은 .NETZ가 이들을 병합하지 않고 별도의 어셈블리를 유지하지만 하나의 패키지로 묶여 있다는 점입니다.

.NETZ는 Microsoft .NET Framework 실행 파일 (EXE, DLL)을 압축하고 압축하여이를 더 작게 만드는 오픈 소스 도구입니다.




Related