Osadzanie bibliotek DLL w skompilowanym pliku wykonywalnym

Czy jest możliwe osadzenie istniejącej biblioteki DLL w skompilowanym pliku wykonywalnym C# (tak, że masz tylko jeden plik do dystrybucji)? Jeśli to możliwe, jak można to zrobić?

Normalnie, nie przeszkadza mi pozostawienie bibliotek DLL Na zewnątrz i posiadanie programu instalacyjnego do obsługi wszystkiego, ale było kilka osób w pracy, które mnie o to pytały i szczerze Nie wiem.

Author: cs95, 2008-10-09

16 answers

Bardzo polecam korzystanie z Costury.Fody - zdecydowanie najlepszy i najłatwiejszy sposób osadzania zasobów w Twoim zespole. Jest dostępny jako pakiet NuGet.

Install-Package Costura.Fody

Po dodaniu go do projektu, automatycznie osadzi wszystkie referencje skopiowane do katalogu wyjściowego w Twoim głównym zestawie. Możesz wyczyścić osadzone pliki, dodając obiekt docelowy do projektu:

Install-CleanReferencesTarget

Będziesz także mógł określić, czy dołączyć pdb, wykluczyć niektóre zespoły lub wyciąganie zespołów w locie. O ile wiem, obsługiwane są również niezarządzane zespoły.

Update

Obecnie niektórzy ludzie próbują dodać wsparcie dla DNX .

Update 2

Dla ostatniej wersji Fody, musisz mieć MSBuild 16 (tak Visual Studio 2019). Fody w wersji 4.2.1 zrobi MSBuild 15. (reference: Fody jest obsługiwane tylko w MSBuild 16 i nowszych. Aktualna wersja: 15)

 787
Author: Matthias,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-04 16:14:40

Po prostu kliknij prawym przyciskiem myszy projekt w Visual Studio, wybierz Właściwości projektu -> Zasoby - > Dodaj zasób - > Dodaj istniejący plik… I dołącz poniższy kod do swojej aplikacji.xaml.cs lub odpowiednik.

public App()
{
    AppDomain.CurrentDomain.AssemblyResolve +=new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}

System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    string dllName = args.Name.Contains(',') ? args.Name.Substring(0, args.Name.IndexOf(',')) : args.Name.Replace(".dll","");

    dllName = dllName.Replace(".", "_");

    if (dllName.EndsWith("_resources")) return null;

    System.Resources.ResourceManager rm = new System.Resources.ResourceManager(GetType().Namespace + ".Properties.Resources", System.Reflection.Assembly.GetExecutingAssembly());

    byte[] bytes = (byte[])rm.GetObject(dllName);

    return System.Reflection.Assembly.Load(bytes);
}

Oto mój oryginalny wpis na blogu: http://codeblog.larsholm.net/2011/06/embed-dlls-easily-in-a-net-assembly/

 95
Author: Lars Holm Jensen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-11 18:27:37

Jeśli są rzeczywiście zarządzanymi zespołami, możesz użyć ILMerge . W przypadku rodzimych bibliotek DLL będziesz miał trochę więcej pracy.

: Jak C++ Windows dll może być scalony w C# aplikacji EXE?

 88
Author: Shog9,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-05-17 17:32:33

Tak, możliwe jest łączenie plików wykonywalnych. NET z bibliotekami. Istnieje wiele narzędzi dostępnych do wykonania zadania:

  • ILMerge jest narzędziem, które może być używane do łączenia wielu zestawów. NET w jeden zestaw.
  • mono mkbundle, pakuje exe i wszystkie zespoły z libmono w jeden pakiet binarny.
  • IL-Repack jest FLOSSOWĄ alternatywą dla ILMerge, z kilkoma dodatkowymi funkcjami.

DODATKOWO można być połączone z Linkerem Mono , który usuwa nieużywany kod i sprawia, że powstały zespół jest mniejszy.

Inną możliwością jest użycie .NETZ , który nie tylko pozwala na kompresję zespołu, ale także może spakować biblioteki DLL bezpośrednio do exe. Różnica w stosunku do wyżej wymienionych rozwiązań jest taka .NETZ nie łączy ich, pozostają oddzielnymi składami, ale są pakowane w jeden pakiet.

.NETZ jest narzędziem open source, które kompresuje i pakuje Pliki Wykonywalne Microsoft. NET Framework (EXE, DLL), aby je zmniejszyć.

 26
Author: Bobby,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-08 18:53:54

ILMerge może łączyć zespoły w jeden zespół pod warunkiem, że zespół zarządza tylko kodem. Możesz użyć aplikacji wiersza poleceń lub dodać odwołanie do exe i programowo scalać. Dla wersji GUI jest Eazfuscator , a także .Netz oba są wolne. Płatne aplikacje to BoxedApp i SmartAssembly .

Jeśli musisz połączyć zespoły z niezarządzanym kodem, proponuję SmartAssembly . Nigdy nie miałem czkawka z SmartAssembly ale ze wszystkimi innymi. Tutaj może osadzić wymagane zależności jako zasoby do głównego exe.

Możesz zrobić to wszystko ręcznie, nie martwiąc się, czy assembly jest zarządzany lub w trybie mieszanym, osadzając dll do swoich zasobów, a następnie opierając się na Assembly AppDomain ResolveHandler. Jest to rozwiązanie jednego przystanku, przyjmując najgorszy przypadek, tj. zespoły z niezarządzanym kodem.

static void Main()
{
    AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
    {
        string assemblyName = new AssemblyName(args.Name).Name;
        if (assemblyName.EndsWith(".resources"))
            return null;

        string dllName = assemblyName + ".dll";
        string dllFullPath = Path.Combine(GetMyApplicationSpecificPath(), dllName);

        using (Stream s = Assembly.GetEntryAssembly().GetManifestResourceStream(typeof(Program).Namespace + ".Resources." + dllName))
        {
            byte[] data = new byte[stream.Length];
            s.Read(data, 0, data.Length);

            //or just byte[] data = new BinaryReader(s).ReadBytes((int)s.Length);

            File.WriteAllBytes(dllFullPath, data);
        }

        return Assembly.LoadFrom(dllFullPath);
    };
}

Kluczem jest zapis bajtów do pliku i ładowanie z jego miejsce. Aby uniknąć problemów z kurczakiem i jajkiem, musisz upewnić się, że zadeklarowałeś obsługę przed uzyskaniem dostępu do assembly i że nie uzyskasz dostępu do członków assembly (lub nie tworzysz instancji czegokolwiek, co ma do czynienia z assembly) wewnątrz części ładującej (rozwiązującej assembly). Zadbaj również, aby upewnić się, że {[3] } nie jest katalogiem tymczasowym, Ponieważ pliki tymczasowe mogą zostać usunięte przez inne programy lub przez Ciebie (NIE, że zostaną usunięte, gdy twój program uzyskuje dostęp do biblioteki dll, ale przynajmniej jej uciążliwość. AppData jest dobra lokalizacja). Należy również zauważyć, że trzeba zapisać bajty za każdym razem, nie można załadować z lokalizacji tylko ' bo dll już tam mieszka.

Dla zarządzanych bibliotek DLL, nie trzeba zapisywać bajtów, ale ładować bezpośrednio z lokalizacji biblioteki dll, lub po prostu czytać bajty i ładować zespół z pamięci. Tak czy inaczej:

    using (Stream s = Assembly.GetEntryAssembly().GetManifestResourceStream(typeof(Program).Namespace + ".Resources." + dllName))
    {
        byte[] data = new byte[stream.Length];
        s.Read(data, 0, data.Length);
        return Assembly.Load(data);
    }

    //or just

    return Assembly.LoadFrom(dllFullPath); //if location is known.

Jeśli montaż jest w pełni niezarządzany, możesz zobaczyć ten link lub to Jak ładować takie biblioteki DLL.

 20
Author: nawfal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:23

Fragment Jeffreya Richtera jest bardzo dobry. Krótko mówiąc, dodaj bibliotekę jako osadzone zasoby i dodaj callback przed czymkolwiek innym. Oto wersja kodu (znaleziona w komentarzach na jego stronie), którą umieściłem na początku głównej metody dla aplikacji konsolowej (tylko upewnij się, że wszelkie wywołania, które używają biblioteki są w innej metodzie do 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);
            }
        };
 16
Author: Steve,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-06 07:04:50

Aby rozwinąć na @Bobby ' s asnwer powyżej. Możesz edytować swoje .csproj używa IL-Repack do automatycznego spakowania wszystkich plików w jeden zespół podczas budowania.

  1. zainstaluj pakiet NuGet ILRepack.MSBuild.Pakiet zadań z Install-Package ILRepack.MSBuild.Task
  2. Edytuj sekcję AfterBuild swojego .csproj

Oto prosta próbka, która łączy Przykładassemblytomerge.dll do wyjścia projektu.

<!-- ILRepack -->
<Target Name="AfterBuild" Condition="'$(Configuration)' == 'Release'">

   <ItemGroup>
    <InputAssemblies Include="$(OutputPath)\$(AssemblyName).exe" />
    <InputAssemblies Include="$(OutputPath)\ExampleAssemblyToMerge.dll" />
   </ItemGroup>

   <ILRepack 
    Parallel="true"
    Internalize="true"
    InputAssemblies="@(InputAssemblies)"
    TargetKind="Exe"
    OutputFile="$(OutputPath)\$(AssemblyName).exe"
   />
</Target>
 14
Author: Josh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:59

Możesz dodać biblioteki dll jako osadzone zasoby, a następnie rozpakować je w katalogu aplikacji podczas uruchamiania (po sprawdzeniu, czy już tam są).

Pliki konfiguracyjne są jednak tak łatwe do wykonania, że nie sądzę, aby było to tego warte.

EDIT: ta technika byłaby łatwa w przypadku. NET assemblies. Z non-.NET biblioteki DLL byłoby o wiele więcej pracy(musiałbyś dowiedzieć się, gdzie rozpakować pliki i zarejestrować je i tak dalej).

 8
Author: MusiGenesis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-09 23:24:12

. NET Core 3.0 natywnie obsługuje kompilację do jednego .exe

Funkcja jest włączona przy użyciu następującej właściwości w pliku projektu (."csproj"): {]}

    <PropertyGroup>
        <PublishSingleFile>true</PublishSingleFile>
    </PropertyGroup>

Odbywa się to bez żadnego zewnętrznego narzędzia.

Zobacz moją odpowiedź na to pytanie Po Więcej Szczegółów.
 8
Author: Marcell Toth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-01 19:57:26

Kolejnym produktem, który poradzi sobie z tym elegancko jest SmartAssembly, w SmartAssembly.com . Ten produkt, oprócz scalenia wszystkich zależności w jedną bibliotekę DLL, (opcjonalnie) zaciemni kod, usunie dodatkowe metadane w celu zmniejszenia rozmiaru pliku wynikowego, a także może faktycznie zoptymalizować IL w celu zwiększenia wydajności pracy.

Istnieje również pewien rodzaj globalnej funkcji obsługi wyjątków/raportowania, którą dodaje do oprogramowania (jeśli jest to pożądane), która może być przydatna. I believe posiada również interfejs API wiersza poleceń, dzięki czemu można uczynić go częścią procesu budowania.

 8
Author: Nathan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-12-02 07:01:47

Ani podejście ILMerge, ani Obsługa zdarzenia AssemblyResolve przez Larsa Holma Jensena nie będą działać dla hosta wtyczki. Powiedzmy, że plik wykonywalny H ładuje zespół Pdynamicznie i uzyskuje do niego dostęp poprzez interfejs IP zdefiniowany w oddzielnym zespole. Aby osadzić IP W H należy dokonać niewielkiej modyfikacji kodu:

Dictionary<string, Assembly> loaded = new Dictionary<string,Assembly>();
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{   Assembly resAssembly;
    string dllName = args.Name.Contains(",") ? args.Name.Substring(0, args.Name.IndexOf(',')) : args.Name.Replace(".dll","");
    dllName = dllName.Replace(".", "_");
    if ( !loaded.ContainsKey( dllName ) )
    {   if (dllName.EndsWith("_resources")) return null;
        System.Resources.ResourceManager rm = new System.Resources.ResourceManager(GetType().Namespace + ".Properties.Resources", System.Reflection.Assembly.GetExecutingAssembly());
        byte[] bytes = (byte[])rm.GetObject(dllName);
        resAssembly = System.Reflection.Assembly.Load(bytes);
        loaded.Add(dllName, resAssembly);
    }
    else
    {   resAssembly = loaded[dllName];  }
    return resAssembly;
};  

Sztuczka, aby poradzić sobie z powtarzającymi się próbami rozwiązania tego samego zestawu i zwrócenia istniejącego zamiast tworzenia nowego przykład.

EDIT: Aby nie zepsuć serializacji. NET, upewnij się, że zwrócisz null dla wszystkich zestawów, które nie są osadzone w Twoim zestawieniu, tym samym domyślając się standardowego zachowania. Lista tych bibliotek znajduje się pod adresem:

static HashSet<string> IncludedAssemblies = new HashSet<string>();
string[] resources = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames();
for(int i = 0; i < resources.Length; i++)
{   IncludedAssemblies.Add(resources[i]);  }

I po prostu zwróć null, jeśli przekazany zestaw nie należy do IncludedAssemblies.

 7
Author: Ant_222,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-07 11:21:23

Może to wydawać się uproszczone, ale WinRar daje możliwość kompresji kilku plików do samorozpakowującego się pliku wykonywalnego.
Posiada wiele konfigurowalnych opcji: końcową ikonę, rozpakuj pliki do podanej ścieżki, plik do wykonania po rozpakowaniu, niestandardowe logo / teksty dla wyskakującego okienka pokazanego podczas rozpakowywania, brak wyskakującego okna, tekst umowy licencyjnej itp.
Może być przydatne w niektórych przypadkach.

 3
Author: Ivan Ferrer Villa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-20 09:03:26

Używam csc.kompilator exe wywoływany z a .skrypt vbs.

W Twoim xyz.skrypt cs, dodaj następujące wiersze po dyrektywach (mój przykład jest dla 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"

Znaczniki ref, res i ico zostaną odebrane przez .skrypt VBS poniżej, aby utworzyć polecenie csc.

Następnie dodaj wywołanie resolver assembly w głównym:

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

...i dodać sam resolver gdzieś w klasie:

    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);
        }

    }

Nazwę skrypt vbs, aby pasował do .nazwa pliku cs (np. ssh.vbs szuka ssh.cs); to sprawia, że uruchamianie skryptu wiele razy dużo łatwiejsze, ale jeśli nie jesteś idiotą jak ja, wtedy ogólny skrypt mógłby podnieść cel .plik cs z drag-and-drop:

    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)
 2
Author: Mark Llewellyn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-28 13:58:30

Następująca metoda nie używaj zewnętrznych narzędzii automatycznie dołącz wszystkie potrzebne biblioteki DLL (nie wymaga ręcznego działania, wszystko odbywa się przy kompilacji)

Przeczytałem tu wiele odpowiedzi mówiących, aby użyć ILMerge, metoda ILRepack lub Jeffreya Ritchera , ale żadna z nich nie działała z aplikacjami WPF ani nie była łatwa w użyciu.

Gdy masz dużo DLL, może być trudno ręcznie dołączyć ten, którego potrzebujesz w exe. The best metoda, którą znalazłem została wyjaśniona przez Wegged tutaj na StackOverflow

Skopiuj wklej swoją odpowiedź tutaj dla jasności (wszystkie podziękowania dla Wegged)


1) dodaj to do pliku .csproj:

<Target Name="AfterResolveReferences">
  <ItemGroup>
    <EmbeddedResource Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'">
      <LogicalName>%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)</LogicalName>
    </EmbeddedResource>
  </ItemGroup>
</Target>

2) Make your Main Program.cs look like this:

[STAThreadAttribute]
public static void Main()
{
    AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly;
    App.Main();
}

3) Dodaj metodę OnResolveAssembly:

private static Assembly OnResolveAssembly(object sender, ResolveEventArgs args)
{
    Assembly executingAssembly = Assembly.GetExecutingAssembly();
    AssemblyName assemblyName = new AssemblyName(args.Name);

    var path = assemblyName.Name + ".dll";
    if (assemblyName.CultureInfo.Equals(CultureInfo.InvariantCulture) == false) path = String.Format(@"{0}\{1}", assemblyName.CultureInfo, path);

    using (Stream stream = executingAssembly.GetManifestResourceStream(path))
    {
        if (stream == null) return null;

        var assemblyRawBytes = new byte[stream.Length];
        stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length);
        return Assembly.Load(assemblyRawBytes);
    }
}
 2
Author: Ludovic Feltz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-16 06:50:03

Jest to możliwe, ale nie takie proste, aby utworzyć Hybrydowy natywny / zarządzany assembly W C#. Jeśli zamiast tego używasz C++, byłoby to o wiele łatwiejsze, ponieważ kompilator Visual C++ może tworzyć hybrydowe zespoły tak łatwo, jak Wszystko inne.

Jeśli nie masz ścisłego wymogu, aby wyprodukować Hybrydowy montaż, zgodzę się z MusiGenesis, że nie jest to naprawdę warte kłopotu z C#. Jeśli musisz to zrobić, może zamiast tego przyjrzyj się przeniesieniu do C++/CLI.

 0
Author: Chris Charabaruk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-09 23:19:44

Ogólnie rzecz biorąc, potrzebujesz jakiegoś narzędzia do budowania postów, aby wykonać scalenie złożenia, tak jak to opisujesz. Istnieje darmowe narzędzie o nazwie Eazfuscator (eazfuscator.blogspot.com/), który jest przeznaczony do manipulowania kodami bajtowymi, które obsługuje również łączenie zespołów. Możesz dodać to do wiersza poleceń po kompilacji w Visual Studio, aby scalić swoje zespoły, ale twój przebieg będzie się różnić ze względu na problemy, które pojawią się w scenariuszach łączenia zespołów innych niż trival.

Możesz również sprawdzić, czy build make unlility NANT ma możliwość łączenia zespołów po zbudowaniu, ale sam nie jestem wystarczająco zaznajomiony z NANT, aby powiedzieć, czy funkcjonalność jest wbudowana, czy nie.

Istnieje również wiele wtyczek Visual Studio, które będą wykonywać łączenie montażu w ramach budowania aplikacji.

Alternatywnie, jeśli nie musisz tego robić automatycznie, istnieje wiele narzędzi, takich jak ILMerge, które połączą zespoły. Net w jeden plik.

The największym problemem, jaki miałem z scalaniem złożeń, jest to, czy używają one podobnych przestrzeni nazw. Albo, co gorsza, odwołaj się do różnych wersji tego samego dll (moje problemy były na ogół z plikami dll NUnit).

 0
Author: wllmsaccnt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-28 14:00:53