ILMerge generated assembly doesn't run, although log output reports no errors - why is this?

戏子无情 提交于 2019-12-02 20:50:28

ILMerge is great if you wrote all of the assemblies that you're trying to merge, and you know that none of them are making assumptions about assembly organization. But under many circumstances (especially ones where heavy reflection or the Dynamic Language Runtime are involved), ILMerge just doesn't work. Sometimes things fail in surprising and mysterious ways.

When ILMerge fails, Jeffrey Richter has a more reliable way to get applications with multiple DLL dependencies to be deployable as a single assembly.

It isn't without trade-offs, but even the ILMerge author, Mike Barnett, said in the comment thread on that blog post "As the author of ILMerge, I think this is fantastic! If I had known about this, I never would have written ILMerge."

If you can use Richter's method, you won't trip over most of the reflection or dynamism traps.

The implementation steps

  1. Embed all of the third-party assemblies that you depend on in your application's Resources.
  2. Register a ResolveEventHandler with the AppDomain.CurrentDomain.AssemblyResolve event.
  3. When your handler gets called with an assembly that you stashed in Resources, load the assembly.

You do part 3 as follows:

var resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name);
return Assembly.Load(new BinaryReader(resourceStream).ReadBytes(int.MaxValue));
Gábor G.

A fully self-contained executable can be created in Visual Studio 2010 easily, and this method does not require ILMerge at all.

Steps:

  • Create an empty executable project
  • Add your DLLs (and your EXE file) as resources. (Right click on project's name in Solution Explorer, Properties, Resources, Add Resource)

After this Visual Studio will auto-create a new class called Resources, which you have to use in your new project.

  • Add the two methods below to Program.cs to make the final application work.

Then you have to compile your program with Visual Studio and that's it.

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

Perhaps this will not solve your problem, but I think that it is good to verify, that your ilmerged executable doesn't contain references to merged libraries. You can check this with ILSpy (http://wiki.sharpdevelop.net/ILSpy.ashx) - just disassemble your ilmerged executable and check in the tree what assemblies are in references. ILSpy can also help you to verify that your ilmerged executable contains classes from merged assemblies.

Next option could be also to debug assembly bindings when trying to start your ilmerged application (http://msdn.microsoft.com/en-us/library/e74a18c4%28v=VS.100%29.aspx).

You could also try to debug ilmerged assembly to find out if application crashes even before calling main function, or perhaps somewhere inside.

I think that identifying particular type which cannot be found could help to fix the problem.

Check your event viewer for any detailed error messages.

Wrap the body of your void Main(string args[]) method with

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

Also try changing your platform target to x86 for example.

You shouldn't need to specify the .net framework directories on the /lib and /targetplatform command line switches if you specify /targetplatform:v4.

After a few hours of fighting with this issue I deleted my project folder and did a fresh pull from git. I tried cleaned and rebuilt my project and it the same issue. I then compared my coworkers project and inside the *\Library\Build*, I was missing the Results folder. After adding the folder \Library\Build\Results my solution built with no errors.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!