Domanda

Ho un Windows programma in C# che utilizza una dll in C++ per i dati di i/o.Il mio obiettivo è quello di distribuire l'applicazione come un singolo file EXE.

Quali sono i passaggi per creare un file eseguibile?

È stato utile?

Soluzione

Unica Assemblea la Distribuzione di Codice gestito e non Gestito Domenica, 4 Febbraio 2007

.NET gli sviluppatori amano la distribuzione di XCOPY.Essi amano i singoli componenti di un assieme.Almeno mi sento sempre un pò a disagio, se devo usare qualche componente e bisogno di ricordare una lista di file da includere anche con l'assembly principale di tale componente.Così quando, recentemente, ho dovuto sviluppare un codice gestito componente e ha dovuto aumentare con un po ' di codice non gestito da una DLL C (thx a Marcus Heege per aiutare me con questo!), Ho pensato a come rendere più facile per distribuire le due Dll.Se questa fosse solo due assemblee avrei potuto usare ILmerge di imballarli in un solo file.Ma questo non funziona per codice misto di componenti gestiti e non gestiti Dll.

Così heres che cosa mi si avvicinò con una soluzione:

Io includere qualsiasi Dll voglio distribuire con i miei componenti principali assemblea, in quanto le risorse incorporate.Poi ho impostato il costruttore di una classe di estrarre quelle Dll come di seguito.La classe di un costruttore viene chiamato una sola volta all'interno di ogni dominio di applicazione quindi è un neglible overhead, penso.

namespace MyLib
{
    public class MyClass
    {
        static MyClass()
        {
            ResourceExtractor.ExtractResourceToFile("MyLib.ManagedService.dll", "managedservice.dll");
            ResourceExtractor.ExtractResourceToFile("MyLib.UnmanagedService.dll", "unmanagedservice.dll");
        }

        ...

In questo esempio ho inserito due Dll come risorse, di cui uno è un codice non gestito DLL, e uno è un codice gestito DLL (solo a scopo dimostrativo), per mostrare come questa tecnica funziona per entrambi i tipi di codice.

Il codice per estrarre le Dll nel file di loro è semplice:

public static class ResourceExtractor
{
    public static void ExtractResourceToFile(string resourceName, string filename)
    {
        if (!System.IO.File.Exists(filename))
            using (System.IO.Stream s = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
                using (System.IO.FileStream fs = new System.IO.FileStream(filename, System.IO.FileMode.Create))
                {
                    byte[] b = new byte[s.Length];
                    s.Read(b, 0, b.Length);
                    fs.Write(b, 0, b.Length);
                }
    }
}

Lavorare con un codice gestito assemblea come questa è sempre lo stesso, o quasi.Si fa riferimento è (qui:ManagedService.dll) in componenti principali del progetto (qui:MyLib), ma impostare la Copia Locale di proprietà a false.Inoltre si collega in assemblea come un Elemento Esistente e impostare l'Azione di generazione Risorsa Incorporata.

Per il codice non gestito (qui:UnmanagedService.dll basta link nella DLL come un Elemento Esistente e impostare l'Azione di generazione Risorsa Incorporata.Per accedere alle sue funzioni utilizzare l'attributo DllImport come di consueto, ad es.

[DllImport("unmanagedservice.dll")] public extern static int Add(int a, int b);

Thats it!Non appena si crea la prima istanza della classe con un costruttore statico incorporato Dll di ottenere estratti i file di loro e sono pronti per l'uso, come se si è distribuito il tutto come file separati.Finché si dispone di autorizzazioni di scrittura per la directory di esecuzione dovrebbe funzionare bene per voi.Almeno per il prototipo di codice credo che questo modo di singola assemblea la distribuzione è molto conveniente.

Enjoy!

http://weblogs.asp.net/ralfw/archive/2007/02/04/single-assembly-deployment-of-managed-and-unmanaged-code.aspx

Altri suggerimenti

Provare boxedapp;consente di caricare tutte le Dll dalla memoria.Mi sembra, anche, che si può anche incorporare .net runtime.Buon di creazione di applicazioni standalone...

Utilizzare Fody.Costura nuget

  1. L'apertura della soluzione -> Progetto -> Gestione Pacchetti Nuget
  2. Ricerca per Fody.Costura
  3. Compilare il progetto.

Ecco!!!

Fonte: http://www.manuelmeyer.net/2016/01/net-power-tip-10-merging-assemblies/

Hai provato ILMerge? http://research.microsoft.com/~mbarnett/ILMerge.aspx

ILMerge è un programma di utilità che può essere utilizzato per unire più .NET assembly in un unico assembly.È liberamente disponibile per l'uso da Strumenti e Utilità pagina di Microsoft .NET Framework Developer Center.

Se si sta costruendo l'DLL in C++ con l' /clr bandiera (in tutto o in parte C++/CLI), quindi dovrebbe funzionare:

ilmerge /out:Composite.exe MyMainApp.exe Utility.dll

Non funziona con un normale (nativo) DLL di Windows, tuttavia.

Basta fare clic destro sul progetto in Visual Studio, scegliere Proprietà del Progetto -> Risorse -> Aggiungi Risorsa -> Aggiungi File Esistente... E includere il codice riportato di seguito per la vostra Applicazione.xaml.cs o equivalente.

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

Ecco il mio post originale:http://codeblog.larsholm.net/2011/06/embed-dlls-easily-in-a-net-assembly/

Thinstall è una soluzione.Per un'applicazione di windows nativa vorrei suggerire di incorporamento DLL come un binario risorsa oggetto, quindi l'estrazione è in fase di esecuzione prima ne avete bisogno.

Smart Assemblea può fare questo e altro.Se la dll è codice non gestito, che non consentono di unire le dll per una singola assemblea, invece, è possibile incorporare le dipendenze necessarie, come le risorse per il tuo exe principale.Il suo rovescio, la sua non è libero.

È possibile eseguire questa operazione manualmente, incorporando dll di risorse e quindi fare affidamento sul dominio di applicazione dell'Assemblea ResolveHandler.Quando si tratta di modalità mista dll, ho trovato molte delle varianti e dei sapori di ResolveHandler approccio non funziona per me (tutto quello che leggi dll byte di memoria e lettura).Tutti hanno lavorato per la gestione della dll.Qui è che cosa ha funzionato per me:

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

La chiave qui è quello di scrivere i byte di un file e caricare dalla sua posizione.Per evitare che l'uovo o la gallina problema, è necessario assicurarsi che si dichiara il gestore, prima di accedere assemblea, e non l'assemblea dei soci (o di creare un'istanza di qualcosa che ha a che fare con l'assemblea) all'interno del caricamento (assemblea risoluzione) parte.Inoltre, fare attenzione a garantire GetMyApplicationSpecificPath() non è la directory temp, dal momento che i file temp potrebbe essere tentato di ottenere cancellati da altri programmi o da soli (non che non vengono eliminati, mentre il programma sta accedendo dll, ma almeno il suo un fastidio.AppData è una buona posizione).Si noti inoltre che è necessario scrivere il byte ogni volta, si può caricare da posizione solo perchè la dll si trova già lì.

Se l'assemblea è completamente non gestito, si può vedere questo link o questo come caricare la dll.

PostBuild da Xenocode può un pacchetto gestito e unmanged in un singolo file exe.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top