2011-11-16 25 views
10

Estoy probando ILMerge para un nuevo proyecto, y aunque el archivo .exe parece haberse creado correctamente, no se ejecutará.El ensamblado generado por ILMerge no se ejecuta, aunque el resultado del registro no informa errores. ¿Por qué es esto?

He instalado ILMerge a través del instalador .msi (se encuentra aquí http://www.microsoft.com/download/en/confirmation.aspx?id=17630) y estoy ejecutando un proyecto de prueba utilizando un archivo por lotes. A continuación se muestra el archivo por lotes y el siguiente registro de salida después de ejecutar. Todo aparece bien en los registros, no se informaron errores. Estoy ejecutando .NET Framework 4.0 para este proyecto de prueba.

Cuando intento ejecutar el .exe, falla con un estándar "Este programa ha dejado de funcionar".

He leído que algunas personas tienen problemas al ejecutar .NET 4, pero creo que he agregado los argumentos correctos para manejar esto. Obtengo el mismo resultado si agrego .NET 4 args o no.

¿Alguien puede ver por qué esto puede ser? Gracias por adelantado.

por lotes de archivos de salida

REM Clear directory first 

CD C:\WORKING\DIR\TestILMerge\TestILMerge\bin\Debug\CombinedDLL 

DEL . /s/q 

REM Change dir to iLMerge install (installed via msi installer) 
REM Installer Download: http://www.microsoft.com/download/en/confirmation.aspx?id=17630 

CD C:\Program Files (x86)\Microsoft\ILMerge\ 

REM Combine assemblies with logging 

ilmerge.exe /lib:"C:\Windows\Microsoft.NET\Framework\v4.0.30319" /lib:"C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies" /t:exe /log:C:\WORKING\DIR\TestILMerge\TestILMerge\bin\Debug\CombinedDLL\MergeLog.txt /target:winexe /targetplatform:v4,C:\Windows\Microsoft.NET\Framework\v4.0.30319 /out:C:\WORKING\DIR\TestILMerge\TestILMerge\bin\Debug\CombinedDLL\CombinedDLL.exe C:\WORKING\DIR\TestILMerge\TestILMerge\bin\Debug\TestILMerge.exe C:\WORKING\DIR\TestILMerge\TestDLL2\bin\Debug\TestDLL2.dll C:\WORKING\DIR\TestILMerge\TestDLL3\bin\Debug\TestDLL3.dll 

Log:

ILMerge version 2.11.1103.0 
Copyright (C) Microsoft Corporation 2004-2006. All rights reserved. 
ILMerge /lib:C:\Windows\Microsoft.NET\Framework\v4.0.30319 /lib:C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies /t:exe /log:C:\WORKING\DIR\TestILMerge\TestILMerge\bin\Debug\CombinedDLL\MergeLog.txt /target:winexe /targetplatform:v4,C:\Windows\Microsoft.NET\Framework\v4.0.30319 /out:C:\WORKING\DIR\TestILMerge\TestILMerge\bin\Debug\CombinedDLL\CombinedDLL.exe C:\WORKING\DIR\TestILMerge\TestILMerge\bin\Debug\TestILMerge.exe C:\WORKING\DIR\TestILMerge\TestDLL2\bin\Debug\TestDLL2.dll C:\WORKING\DIR\TestILMerge\TestDLL3\bin\Debug\TestDLL3.dll 
Set platform to 'v4', using directory 'C:\Windows\Microsoft.NET\Framework\v4.0.30319' for mscorlib.dll 
Running on Microsoft (R) .NET Framework v2.0.50727 
mscorlib.dll version = 2.0.0.0 
The list of input assemblies is: 
    C:\WORKING\DIR\TestILMerge\TestILMerge\bin\Debug\TestILMerge.exe 
    C:\WORKING\DIR\TestILMerge\TestDLL2\bin\Debug\TestDLL2.dll 
    C:\WORKING\DIR\TestILMerge\TestDLL3\bin\Debug\TestDLL3.dll 
Trying to read assembly from the file 'C:\WORKING\DIR\TestILMerge\TestILMerge\bin\Debug\TestILMerge.exe'. 
    Successfully read in assembly. 
    There were no errors reported in TestILMerge's metadata. 
Trying to read assembly from the file 'C:\WORKING\DIR\TestILMerge\TestDLL2\bin\Debug\TestDLL2.dll'. 
    Successfully read in assembly. 
    There were no errors reported in TestDLL2's metadata. 
Trying to read assembly from the file 'C:\WORKING\DIR\TestILMerge\TestDLL3\bin\Debug\TestDLL3.dll'. 
    Successfully read in assembly. 
    There were no errors reported in TestDLL3's metadata. 
Checking to see that all of the input assemblies have a compatible PeKind. 
    TestILMerge.PeKind = ILonly, Requires32bits 
    TestDLL2.PeKind = ILonly 
    TestDLL3.PeKind = ILonly 
All input assemblies have a compatible PeKind value. 
Using assembly 'TestILMerge' for assembly-level attributes for the target assembly. 
Merging assembly 'TestILMerge' into target assembly. 
Merging assembly 'TestDLL2' into target assembly. 
Merging assembly 'TestDLL3' into target assembly. 
Copying 2 Win32 Resources from assembly 'TestILMerge' into target assembly. 
Transferring entry point 'TestILMerge.Program.Main(System.String[])' from assembly 'TestILMerge' to assembly 'CombinedDLL'. 
    There were no errors reported in the target assembly's metadata. 
ILMerge: Writing target assembly 'C:\WORKING\DIR\TestILMerge\TestILMerge\bin\Debug\CombinedDLL\CombinedDLL.exe'. 
Location for referenced assembly 'mscorlib' is 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll' 
    There were no errors reported in mscorlib's metadata. 
ILMerge: Done. 

ACTUALIZACIÓN: Aquí es el Desensamblaje - se ve como yo esperaría que

Desensamblaje

enter image description here

ACTUALIZACIÓN 2

he encontrado que el componente funciona si hago referencia a otro proyecto y utilizo como un conjunto, pero no es un archivo ejecutable independiente.

Respuesta

8

ILMerge es ideal si escribió todos los ensamblajes que está intentando fusionar, y sabe que ninguno de ellos está haciendo suposiciones sobre la organización del ensamblaje. Pero bajo muchas circunstancias (especialmente aquellas en las que se requiere reflexión intensa o Dynamic Language Runtime), ILMerge simplemente no funciona. Algunas veces las cosas fallan de maneras sorprendentes y misteriosas.

Cuando falla ILMerge, Jeffrey Richter tiene a more reliable way to get applications with multiple DLL dependencies to be deployable as a single assembly.

No es sin compensaciones, pero incluso el autor de ILMerge, Mike Barnett, dijo en el hilo de comentarios en esa entrada del blog "¡Como autor de ILMerge, creo que esto es fantástico! Si hubiera sabido sobre esto , Nunca hubiera escrito ILMerge ".

Si puede usar el método de Richter, no tropezará con la mayoría de las trampas de reflexión o dinamismo.

La implementación pasos

  1. Insertar todos los conjuntos de terceros que usted depende de los recursos de su aplicación.
  2. Registre ResolveEventHandler con el evento AppDomain.CurrentDomain.AssemblyResolve.
  3. Cuando se llama a su controlador con un ensamblaje que ha guardado en Recursos, cargue el ensamblaje.

los separe 3 como sigue:

var resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name); 
return Assembly.Load(new BinaryReader(resourceStream).ReadBytes(int.MaxValue)); 
+0

Wow gracias. No lo intenté pero parece una forma más ordenada de hacerlo. Ilmerge no es fácil de configurar. Utilizaré este método si encuentro esto de nuevo. – gb2d

+2

[Este tutorial brinda más detalles] (http://adamthetech.com/2011/06/embed-dll-files-within-an-exe-c-sharp-winforms/) que Richters, que no pude seguir porque no hubo "Recurso incrustado" "Acción de compilación". – thinkOfaNumber

+0

¿Esta solución también es apropiada si solo quiero incluir algunas de las DLL a las que se hace referencia? – Simone

1

Quizás esto no resuelva su problema, pero creo que es bueno verificar que su ejecutable ilustrged no contenga referencias a bibliotecas fusionadas. Puede comprobar esto con ILSpy (http://wiki.sharpdevelop.net/ILSpy.ashx) - simplemente desmonte su ejecutable ilmerged y compruebe en el árbol qué ensamblajes están en las referencias. ILSpy también puede ayudarlo a verificar que su ejecutable ilmerged contenga clases de ensamblados fusionados.

La siguiente opción podría ser también para depurar enlaces de ensamblaje al intentar iniciar su aplicación ilmerged (http://msdn.microsoft.com/en-us/library/e74a18c4%28v=VS.100%29.aspx).

También podría intentar depurar el ensamblaje de la lámpara para averiguar si la aplicación se bloquea incluso antes de llamar a la función principal, o quizás en algún lugar dentro.

Creo que la identificación de un tipo particular que no se puede encontrar podría ayudar a solucionar el problema.

+0

No hay conjuntos fusionados incluidos. He adjuntado la ventana IL Disassembler – gb2d

0

Revise su visor de eventos para cualquier mensaje de error detallado.

envolver el cuerpo de su método de void Main(string args[]) con

try 
{ 
... 
} 
catch (Exception ex) 
{ 
    Console.WriteLine(ex.ToString()); 
} 

También trate de cambiar su destino a la plataforma x86, por ejemplo.

No debería necesitar especificar los directorios .net framework en los conmutadores de línea de comando /lib y /targetplatform si especifica /targetplatform:v4.

4

Un ejecutable totalmente autónomo se pueden crear en Visual Studio 2010 con facilidad, y este método no requiere ILMerge en absoluto.

Pasos:

  • crear un proyecto ejecutable vacío
  • añaden sus DLL (y su archivo EXE) como recursos. (Haga clic con el botón derecho en el nombre del proyecto en Explorador de soluciones, Propiedades, Recursos, Agregar recurso)

Después de esto, Visual Studio creará automáticamente una nueva clase llamada Recursos, que debe usar en su nuevo proyecto.

  • Agregue los dos métodos siguientes a Program.cs para que la aplicación final funcione.

Luego tiene que compilar su programa con Visual Studio y listo.

static void Main(string[] args) 
{ 
    // Load your assembly with the entry point from resources: 
    Assembly start = Assembly.Load((byte[]) Properties.Resources.NameOfDllOrExeInYourResources); 
    Type t = start.GetType("Foo.Bar.Program"); 

    // Install the resolver event 
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); 

    // Find Program.Main in the loaded assembly 
    MethodInfo m = t.GetMethod("Main", BindingFlags.Public | BindingFlags.Static); 

    // Launch the application 
    m.Invoke(null, new object[] { args }); 
} 

static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 
{ 
    string assemblyName = new AssemblyName(args.Name).Name.Replace('.', '_'); 

    // Locate and load the contents of the resource 
    byte[] assemblyBytes = (byte[]) Properties.Resources.ResourceManager.GetObject(assemblyName, Properties.Resources.Culture); 

    // Return the loaded assembly 
    return Assembly.Load(assemblyBytes); 
} 
+0

Puse mi código de referencia en una clase separada y reduje esto a solo: 'Assembly start = ....', 'AppDomain.CurrentDomain.AssemblyResolve + = ...', mantuve el código de EventHandler y luego llamé a la clase y Funciona de maravilla. También edité el EventHandler para llamar específicamente a la biblioteca que quería, pero de cualquier manera, muy fácil, muchas gracias. – GibralterTop

0

Después de unas horas de luchar con este problema, eliminé la carpeta de mi proyecto e hice una nueva extracción de git. Intenté limpiar y reconstruir mi proyecto y es el mismo problema. Luego comparé el proyecto de mis compañeros de trabajo y dentro del * \ Library \ Build *, me faltaba la carpeta .Después de agregar la carpeta \ Library \ Build \ Results mi solución construida sin errores.

Cuestiones relacionadas