Un’applicazione Windows .NET può essere compressa in un singolo .exe?

Non ho molta familiarità con le applicazioni desktop .NET (utilizzando Visual Studio 2005 ). È ansible eseguire l’intera applicazione da un singolo file .exe?

Sì, puoi usare lo strumento ILMerge .

Oggi, nel 2015, puoi usare Costura.Fody per questo. Usarlo equivale ad aggiungere il pacchetto NuGet al tuo progetto e ricompilare. Non sono sicuro che funzioni con Visual Studio 2005 come nella domanda, ma non è nemmeno l’anno 2008. L’ho usato in alcuni dei miei progetti e ha funzionato alla grande.

Fody è un Code Weaver per uso generale che è gratuito e open source. L’idea di base che consente la post-elaborazione del codice .NET compilato per migliorarlo con le funzionalità. Ad esempio, la registrazione può essere aggiunta a ogni chiamata di metodo, ecc. Nel nostro caso, impacchetta i file DLL dipendenti nelle risorse dell’assembly, in modo che possano essere caricati durante il runtime del programma come se fossero dipendenze autonome.

Sì. In .NET è ansible incapsulare l’intera applicazione come un singolo file EXE. Assicurati che la tua soluzione contenga solo un progetto di applicazione Windows (e nessun altro progetto tranne per le configurazioni).

Il file EXE creato dal progetto .NET non sarà un file eseguibile autonomo, ma l’unica dipendenza sarà il runtime .NET (a meno che non si aggiungano riferimenti ad altri assembly DLL). Se si utilizza .NET 2.0 (che consiglio), il runtime viene preinstallato su PC più recenti ed è molto semplice e veloce da configurare su macchine precedenti (l’installatore è di circa 23 MB).

Se la tua app deve fare riferimento ad altri assembly (come una DLL di accesso ai dati o un progetto DLL della libreria di classi .NET), puoi utilizzare uno degli strumenti a cui fanno riferimento altri poster qui per combinare il tuo EXE e tutte le DLL di riferimento in un singolo file EXE . Tuttavia, la pratica convenzionale imporrebbe semplicemente la distribuzione del file EXE insieme a qualsiasi DLL dipendente come file separati . In .NET, la distribuzione di DLL dipendenti è piuttosto semplice: basta metterli nella stessa cartella del file EXE sul computer client e il gioco è fatto.

È buona pratica distribuire l’applicazione (sia essa un file o più) come un programma di installazione a file singolo (un file setup.EXE o setup.MSI). .NET viene fornito con modelli di progetto di distribuzione che possono creare programmi di installazione per voi abbastanza facilmente.

Un po ‘fuori tema: è ansible utilizzare NGEN per compilare l’applicazione .NET come un EXE nativo, ma dipende comunque dal runtime .NET. Il vantaggio della compilazione nativa è che alcune cose possono essere precompilate, ma non ho mai visto una situazione in cui questo piccolo incremento di prestazioni valga la pena.

C’è uno strumento di terze parti chiamato .NET Reactor che può farlo per te. Non ho usato lo strumento e quindi non sono sicuro di quanto funzioni bene.

Ho usato il pacchetto eseguibile open source .NETZ .NET per comprimere file EXE e DLL in un singolo file EXE. Ecco un esempio da riga di comando per come impacchettare i file DLL in un unico file:

netz -s application.exe foo.dll bar.dll 

Come è stato detto, puoi usare ILMerge .

Potrebbe essere più semplice, tuttavia, se utilizzi la protezione Phoenix gratuita , che protegge anche il tuo codice.

Puoi provare l’utility NBox .

Jeffrey Richter ha scritto nel suo estratto del libro che un metodo di callback con l’evento ResolveAssembly del dominio dell’applicazione può essere registrato per consentire al CLR di trovare assembly di terze parti e file DLL durante l’inizializzazione del programma:

 AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => { String resourceName = "AssemblyLoadingAndReflection." + 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); } }; 

Disclaimer : non ho usato questo da solo. Per quanto ho capito, il client ha ancora bisogno di avere il framework .NET installato.

Sto usando .netshrink me stesso, e fa esattamente quello che ti serve. Comprime gli assembly principale ed extra (file DLL) in un’unica immagine eseguibile.

L’ho usato già da un anno, e non tornerò su ILMerge (si ferma sempre ad un certo punto …).

.netshrink finestra principale dalla pagina del prodotto

Non è necessario dividerlo in più assiemi (che di solito sono progetti all’interno di una soluzione di Visual Studio). Il .NET Framework è richiesto in ogni caso, non c’è modo – ed è il modo giusto – per incorporarlo.

Sì, puoi creare un singolo file EXE. Due buoni articoli sono:

  1. Come includere tutte le DLL correlate in un singolo file EXE
  2. Runtime .NET – singolo file EXE

ILMerge può combinare gli assiemi in un unico assieme purché l’assembly abbia solo codice gestito. È ansible utilizzare l’applicazione riga di comando o aggiungere riferimento al file EXE e unire a livello di codice. Per una versione della GUI, c’è Eazfuscator e anche .Netz , entrambi gratuiti. Le applicazioni a pagamento includono BoxedApp e SmartAssembly .

Se si devono unire assiemi con codice non gestito, suggerirei SmartAssembly . Non ho mai avuto singhiozzo con SmartAssembly , ma con tutti gli altri. Qui, può incorporare le dipendenze richieste come risorse per il tuo file EXE principale.

Puoi fare tutto questo manualmente, senza preoccuparti se un assembly è gestito o in modalità mista incorporando il file DLL nelle tue risorse e poi affidandoti all’assembly ResolveHandler AppDomain. Questa è una soluzione one-stop adottando il caso peggiore, ovvero gli assembly con codice non gestito.

 class Program { [STAThread] 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); }; } } 

Dove Program è il nome della class. La chiave qui è scrivere i byte in un file e caricare dalla sua posizione. Per evitare un problema di gallina e uova, è necessario assicurarsi di dichiarare il gestore prima di accedere all’assieme e di non accedere ai membri dell’assieme (o creare un’istanza di tutto ciò che deve occuparsi dell’assieme) all’interno del caricamento (risoluzione dell’assemblaggio) parte. Assicurati inoltre che GetMyApplicationSpecificPath() non sia una directory temporanea poiché si potrebbe tentare di cancellare file temporanei da altri programmi o da te stesso (non che verranno eliminati mentre il tuo programma sta accedendo al file DLL, ma almeno è una seccatura AppData è una buona posizione). Si noti inoltre che è necessario scrivere i byte ogni volta; non è ansible caricare dalla posizione solo perché il file DLL risiede già lì.

Per i file DLL gestiti, non è necessario scrivere byte, ma caricare direttamente dal percorso del file DLL, o semplicemente leggere i byte e caricare l’assembly dalla memoria. Ad esempio:

 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. 

Se l’assembly è completamente non gestito, puoi vedere questo link o questo come caricare questi file DLL.