The AssemblyResolve event is fired when Assembly.Load (byte ()) is called

So, I have a WPF project that pulls out the DLLs that are used by another project here at my work. This is a mess of dependencies, I used the technique here: http://www.digitallycreated.net/Blog/61/combining-multiple-assemblies-into-a-single-exe-for-a-wpf-application to embed dependencies in one executable file.

Now, when I call a specific method inside one of the dependencies, I push the AssemblyResolve event. My OnResolveAssembly event occurs, it finds the assembly as an embedded resource (cool!) And returns "Assembly.Load (assemblyyRawBytes)". If I remove F11 at this point (with a breakpoint at the beginning of OnResolveAssembly), I get another call to the same event. This is for the same assembly too (args.Name is the same).

If I allow this run, I push the stack overflow, since I can never escape this recursive event call.

MSDN docs don't really say when Assembly.Load might fail, with the exception of a FileNotFoundException or BadImageFormatException.

I tried to disable OnResolveAssembly at that moment before I call Assembly.Load, but then my application dies a mysterious death, even under VS it just goes puff.

I will probably break a few rules here, but some ideas on where to start looking for problems will be welcome.

I'm going to start bothering with a problematic DLL to find out if there are any hints of what's wrong with it (maybe this is a mixed build?).

Here is my OnResolveAssembly handler:

private static Assembly OnResolveAssembly(object sender, ResolveEventArgs args)
{
    Assembly executingAssembly = Assembly.GetExecutingAssembly();
    AssemblyName assemblyName = new AssemblyName(args.Name);

    string path = assemblyName.Name + ".dll";

    if (assemblyName.CultureInfo.Equals(System.Globalization.CultureInfo.InvariantCulture) == false)
    {
        path = String.Format(@"{0}\{1}", assemblyName.CultureInfo, path);
    }
    using (Stream stream = executingAssembly.GetManifestResourceStream(path))
    {
        if (stream == null)
            return null;

        byte[] assemblyRawBytes = new byte[stream.Length];
        stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length);
        assemblyDictionary.Add(assemblyName.Name, Assembly.Load(assemblyRawBytes));
        return assemblyDictionary[assemblyName.Name];
    }
}

Currently, I have resolved it by repeating all my resources and trying Assembly.Load on them and saving them in a dictionary for retrieval (during the OnResolveAssembly event):

[STAThread]
public static void Main()
{
    AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly;
    Assembly executingAssembly = Assembly.GetExecutingAssembly();
    string[] resources = executingAssembly.GetManifestResourceNames();
    foreach (string resource in resources)
    {
        if (resource.EndsWith(".dll"))
        {
            using (Stream stream = executingAssembly.GetManifestResourceStream(resource))
            {
                if (stream == null)
                    continue;

                byte[] assemblyRawBytes = new byte[stream.Length];
                stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length);
                try
                {
                    assemblyDictionary.Add(resource, Assembly.Load(assemblyRawBytes));
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.Print("Failed to load: " + resource + " Exception: " + ex.Message);
                }
            }
        }
    }
    App.Main();
}

private static Assembly OnResolveAssembly(object sender, ResolveEventArgs args)
{
    Assembly executingAssembly = Assembly.GetExecutingAssembly();
    AssemblyName assemblyName = new AssemblyName(args.Name);

    string path = assemblyName.Name + ".dll";

    if (assemblyDictionary.ContainsKey(path))
    {
        return assemblyDictionary[path];
    }
    return null;
}

Everything seems to work fine now (the β€œfailed” build will load in my second fragment), but I would be interested to know why it does not work in the first.

+5
1

[] - .dll(, / ). , , dll AppDomain, , . : AssemblyResolve

, "" AppDomains. , Load (byte []), .

, . : AssemblyResolve, DisallowApplicationBaseProbing = true

, .

BTW. - , . - MyType MyAssembly MyType ?

" .".

+3

All Articles