C# 4.0 Merge .dll assembly with .NET

2019-04-09 19:47发布

问题:

I decided to leave my other question to die, since I thought of a new idea using Jeffrey Richter's method written on this page to merge a .dll library to my application. So I added my .dll file as an embedded resource and also added it as a reference. Then in Program.cs (I have no idea where the code he posted is supposed to go), I added this:

    ...
    [STAThread]
    static void Main()
    {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            string[] args = Environment.GetCommandLineArgs();
            if (args.Length > 1)
                _in = args[1];
            SingleInstanceController controller = new SingleInstanceController();
            controller.Run(args);

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

Am I supposed to change resourceName to something else? Have I added it correctly (in the right place)?

Now the problem is, it still fails to find and load the assembly and I'm not sure what I've done wrong. Any help would be appreciated.

回答1:

Hook to the AssemblyResolve event before the AppDomain tries to resolve references i.e in the entry point and the first line.

The embedded resource name starts with the application name followed by the resource name. ex: ConsoleApplication.Test.dll.



回答2:

Your problem is very similar to this one: C#: How to embed DLL into resourcefile (no dll copy in program directory)

Basically, your AppDomain.AssemblyResolve event handler did not get called because Main failed to compile. Even if it did compile, attaching the event handler should be the first thing you do in main.

My answer to the question above has a working code sample and explanation on why your code does not work.



回答3:

Use the debugger. Set breakpoints on the AssemblyResolve assignment and the lambda body. Single step the code.

Yes, that's too late. Move the assignment. If SingleInstanceController is in such a DLL then the Main() method never even gets started. Move that code into a separate helper method and give it the [MethodImpl(MethodImplOptions.Noinlining)] attribute.

Distributing your program in a single file is already very well supported, it doesn't require any code nor merging DLLs. Also takes care of the desktop shortcut, the file associations and getting .NET installed on old machines. It's called setup.exe