FileNotFoundException when trying to load Autofac as an embedded assembly - c#

Previous versions of Autofac worked, but since they switched to making it a Portable Class Library it won't load.
I tried applying the fix listed here (KB2468871) but it told me that it was not needed.
The error goes away when I move the Autofac.dll file into the same location as the executable. When it loads it from the external DLL it loads fine.
Why won't it work as an embedded DLL?
Here is the exception:
System.IO.FileNotFoundException: Could not load file or assembly 'System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes' or one of its dependencies. The system cannot find the file specified.
Stack trace:
at Autofac.Core.Registration.ComponentRegistration..ctor(Guid id, IInstanceActivator activator, IComponentLifetime lifetime, InstanceSharing sharing, InstanceOwnership ownership, IEnumerable`1 services, IDictionary`2 metadata)
at Autofac.Core.Container..ctor()
at Autofac.ContainerBuilder.Build(ContainerBuildOptions options)
at MyApp.Configuration.Bootstrapper.Run(String[] args) in c:\Dev\MyApp\App\Configuration\Bootstrapper.cs:line 25
at MyApp.Configuration.EntryPoint.Main(String[] args) in c:\Dev\MyApp\App\Configuration\EntryPoint.cs:line 22
If it helps, here is the part of the .csproj file that embeds the DLLs into the executable:
<Target Name="AfterResolveReferences">
<ItemGroup>
<EmbeddedResource Include="#(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'">
<LogicalName>%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)</LogicalName>
</EmbeddedResource>
</ItemGroup>
... and here is the EntryPoint class:
internal static class EntryPoint
{
[STAThread]
private static void Main(params string[] args)
{
AppDomain.CurrentDomain.AssemblyResolve += (sender, e) => loadEmbeddedAssembly(e.Name);
Bootstrapper.Run(args); // must call separate class when using embedded assemblies
}
private static Assembly loadEmbeddedAssembly(string name)
{
var container = Assembly.GetExecutingAssembly();
var path = new AssemblyName(name).Name + ".dll";
using (var stream = container.GetManifestResourceStream(path))
{
if (stream == null)
{
return null;
}
var bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
return Assembly.Load(bytes);
}
}
}

I could easily repro your problem by using Assembly.Load(byte[]) on a PCL library that targeted Silverlight and used a System.Core type, this problem isn't specific to Autofac. It is a rather evil way to load an assembly, about as bad as Assembly.LoadFile(). Not having a loading context is a recipe for DLL Hell.
The CLR has an unenviable job to do with these PCL library references, it needs to magically map the retargetable assembly references to a real one. In other words, the 2.0.5.0 reference needs to be mapped to the correct one for the runtime version, 4.0.0.0 in your case. It can only do this if it has a good idea what the actual runtime version is, not having a loading context makes that difficult. Clearly it doesn't attempt to do so, it fires the AssemblyResolve event again for the 2.0.5.0 reference.
Which is the solution, remarkable simple in hind-sight. Just intercept the resolve request for the retargetable assembly references and use Assembly.Load() to let the CLR sort it out from the loading context of your AppDomain. Alter your AssemblyResolve event handler like this:
private static Assembly loadEmbeddedAssembly(string name)
{
if (name.EndsWith("Retargetable=Yes")) {
return Assembly.Load(new AssemblyName(name));
}
// Rest of your code
//...
}
This worked well in my test app, I trust it will solve your problem with Autofac as well.

Maybe the problem is how you try to load your EmbeddedAssembly.
I have very small knowledge about how you can do it
but i know the following example from code project works fine for me so maybe it will help you :-)
Load DLL From Embedded Resource
(If i misunderstand your question please tell me and i will delete my Answer)

Related

Is there an way to add reference(dll) in parent path in C#?

== compile command ==
csc -r:"../Newtonsoft.Json.dll" test.cs
== exec command ==
mono test.exe
== exec result : dependency error ==
System.IO.FileNotFoundException: Could not load file or assembly 'Newtonsoft.Json, Version=11.0.0.0, Culture=neutral,
PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies.
"Newtonsoft.Json.dll" this file is located in parent path. so I added a reference about dll and compile succeeded, but when I executed the exe file, it failed to get dll reference I added.
And when I put cs file and dll file together in the same directory, it worked very well, but that's not what I wanted.
Is there a solution to add a reference from dll file which is located in parent path using command line interface?
I used csc for compiler and mono for execution.
Thanks.
References are pathless. What that means is that wherever the assembly resides, all your program knows is that it has a reference to Newtonsoft.Json, Version=x.x.x.x, Culture=... and so on. You can do some things with the application configuration (application.config or myprogram.exe.config) to organize things into subfolders (using the probing setting) or specify a URL location for the file (using the codebase setting). You can set up the environment to change the search path and so on.
Or you can add some runtime code that allows you to override the default behavior and the call Assembly.LoadFrom to provide a full path to the file. You can either do it as part of your initialization or in a handler for the AppDomain.AssemblyResolve event - which is generally better method since it will only be called when the assembly is actually needed.
For example:
using System.IO;
using System.Reflection;
static class ParentPathResolver
{
public static void Init()
{
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(Resolve);
}
private static Assembly? Resolve(object? sender, ResolveEventArgs args)
{
var filename = new AssemblyName(args.Name).Name + ".dll";
var fullname = Path.GetFullPath(Path.Combine("..", filename));
if (File.Exists(fullname))
return Assembly.LoadFrom(fullname);
return null;
}
}
Of course you can add your own code to the Resolve method to search pretty much anywhere, just as long as you don't get caught in a resolution loop. I've used the AssemblyResolve event to do fun things like loading assemblies from compressed resources.

Some types could not be loaded from a dll that was compiled from a local project

Setup
I am working on a C# project without external dependencies, named "Hopper". I have split it up into a couple of different modules, each contained within a corresponding sub-folder. The relevant ones for the problem are the following:
Utils/Hopper.Utils.csproj
Shared/Hopper.Shared.csproj
Core/Hopper.Core.csproj, which references Utils and Shared, more details later
Mine/Hopper.Mine.csproj, which references Core
All of these target .NET 4.8, including Hopper.Core.
I have set the AssemblyName property for each of the projects to the corresponding string. For example, the Hopper.Utils.csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net4.8</TargetFramework>
<AssemblyName>Hopper.Utils</AssemblyName>
</PropertyGroup>
</Project>
Hopper.Core.csproj references the other projects via ProjectReference, like so:
<ItemGroup>
<ProjectReference Include="..\Utils\Hopper.Utils.csproj" />
<ProjectReference Include="..\Shared\Hopper.Shared.csproj" />
</ItemGroup>
Hopper.Mine.csproj, created for testing purposes, references core like this:
<ItemGroup>
<ProjectReference Include="..\Core\Hopper.Core.csproj" />
</ItemGroup>
The Hopper.Core project contains some types, both classes and structs. Some source files have been autogenerated by a tool and contain #pragma warning disable at the top. (Removing it did not help).
The two projects referenced by Hopper.Core just contain some types and attributes, used by Core, so nothing of interest to the problem. They do not reference any other projects or dll's.
The problem
I am able to compile Hopper.Mine by running dotnet build in the sub-folder with the project file. I am able to see the output dll's of the referenced sub-projects in bin/Debug/net4.8/Hopper.Whatever.dll under each project's folder. Intellisense in VSCode also works correctly and does not report any errors.
Hopper.Mine has a single class with a Main function, created for a test. It lists the types of Hopper.Core that have loaded successfully, and reports the ones that have not been loaded:
using System;
using System.Reflection;
using System.Text;
namespace Hopper.Mine
{
public class Program
{
public static void Main(string[] args)
{
Assembly lib = typeof(Hopper.Core.Action).Assembly;
Type[] types;
try
{
types = lib.GetTypes();
}
catch (ReflectionTypeLoadException ex)
{
StringBuilder sb = new StringBuilder();
foreach (Exception exSub in ex.LoaderExceptions)
{
Console.WriteLine(exSub.Message);
}
types = ex.Types;
}
foreach (Type type in types)
{
if (type != null)
Console.WriteLine(type.FullName);
}
}
}
}
Running this code, I can see a bunch of problematic types, some of which repeat, and the rest of types that have loaded successfully:
Could not load type 'Hopper.Core.Stat.Attack' from assembly 'Hopper.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
Could not load type 'Hopper.Core.Stat.Dig' from assembly 'Hopper.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
Could not load type 'Hopper.Core.Stat.Move' from assembly 'Hopper.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
Could not load type 'Hopper.Core.Stat.Push' from assembly 'Hopper.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
Could not load type 'Hopper.Core.Stat.Attack' from assembly 'Hopper.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
Could not load type 'Hopper.Core.Stat.Attack' from assembly 'Hopper.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
... more errors here ...
Hopper.Core.DirectedPredict
Hopper.Core.UndirectedPredict
Hopper.Core.DirectedDo
... more types here ...
Hopper.Core.Stat.Attack+Source+Resistance
Hopper.Core.Stat.Push+Source+Resistance
To be noted 4 things:
The types that failed to load are all structs and derive from IStat.
The source files with these types have been autogenerated by a tool (other files generated by the tool load without errors).
The types do not reference any types from Hopper.Shared or Hopper.Utils.
Some of the types have nested structs, up to 3 level deep, some of the deeper ones seem to have loaded successfully.
I am pretty sure that the dll output from the Hopper.Core's output folder is identical to the one in the output folder of Hopper.Mine. I am also pretty sure that the right dll is linked against when I start the program (I've tried debugging with VS, where I can see which dll is being linked against and the paths matched).
I have tried removing AssemblyName properties, renaming csproj files from Hopper.Whatever.csproj to Hopper_Whatever.csproj, I've obviously tried cleaning up any previous output dll's and building from scratch, none of which helped. I have also been able to reproduce this on a different machine with the exact same results.
I have tried looking at the Hopper.Core dll with a decompiler, ILSpy. I am able to see the "missing" types as they are in code.
I have searched on google for hours for a problem like mine, to no avail. I have found many cases of people setting up their project files incorrectly, due to which they unexpectedly link against a different version of the dll than they expected. For some, such dependency showed up in requirements of one of the referenced third party projects. Some blame GAC for providing incorrect version of the dll. However, I'm pretty sure that my projects are set up right (+ the set up is pretty simple and no third party projects are being referenced) and I am referencing the right dll's (since I can see my types in it). It kind of seems like the types are 'declared' in the dll, but not 'defined' (sort of), so the dll's turn out corrupted. But then why would the decompilation not fail? So I'm currently completely stuck on this.
Loading the assembly manually
I have tried linking against the dll's dynamically, by their names. Listing the types imported from Hopper.Shared and Hopper.Utils works, however, when I try it with Hopper.Core, I get the same output as the example above.
To achieve this, I have copied the previous dll's from the output over to a new folder, removed the reference from Hopper.Mine, compiled the new code with dotnet build, after which moved the executable to the new folder and finally ran it in the console. The code:
using System;
using System.Reflection;
using System.Text;
namespace Hopper.Mine
{
public class Program
{
public static void Main(string[] args)
{
Assembly shared = Assembly.LoadFrom("Hopper.Shared.dll");
Assembly utils = Assembly.LoadFrom("Hopper.Utils.dll");
Assembly core = Assembly.LoadFrom("Hopper.Core.dll");
Type[] types;
try
{
types = core.GetTypes();
}
catch (ReflectionTypeLoadException ex)
{
StringBuilder sb = new StringBuilder();
foreach (Exception exSub in ex.LoaderExceptions)
{
Console.WriteLine(exSub.Message);
}
types = ex.Types;
}
foreach (Type type in types)
{
if (type != null)
Console.WriteLine(type.FullName);
}
}
}
}
To reproduce
If it helps, you may try running my code. Here's the github link to the current state of the project. In order to run it, you need:
.NET 4.8 installed.
Clone the repository from the link above.
Some code is still missing. You need to run the project in the folder Meta to generate it. Just run dotnet run in the Meta folder.
Now you can run the Mine subproject.
Found out the reason. There is a bug in the CLR type system that has been around for 6 years. Basically, fields (either static or non-static) of type of a generic struct declared in other structs cause this behavior. See this github thread for more details.
In my case, I have been able to make a shorter version that illustrates the bug.
public struct Index<T>
{
}
public struct Test
{
public static Index<Test> Index;
}
Use the following code to test the program:
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine(typeof(Test).Assembly.GetTypes());
}
}
When the code is run, the following error is thrown:
Unhandled Exception: System.TypeLoadException: Could not load type 'Hopper.Mine.Test' from assembly 'Hopper.Mine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
at Hopper.Mine.Program.Main(String[] args)
However, there is an easy sort of workaround for this. Changing Test from struct to class works:
// This works!
public struct Index<T>
{
}
public class Test
{
public static Index<Test> Index;
}
That may not be acceptable in some cases. So here is another workaround — storing the static field in an array and accessing it with a property also works:
public struct Index<T>
{
}
public struct Test
{
public static Index<Test> Index { get => index[0]; set => index[0] = value; }
public static Index<Test>[] index = new Index<Test>[1];
}

Assembly.Load doesn't load a specific version of it

for an auto update logic, I'd like to load a specific version of an assembly. I'm trying to use Assembly.Load method with either assemlyName string or AssemblyName class parameter. For example:
string aname = "MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
var asm = Assembly.Load(aname);
This code happily loads v1.0.0.0 of MyAssembly, which I've referenced normally.
The challenge here is to load a specific version of MyAssembly. My strategy for this has been to wire up AssemblyResolve event (making sure that assembly loading doesn't happen in main method since I've read that it doesn't work there). Then I'd be debugging thru and manually changing the version number of the string from "1.0.0.0" to "2.0.0.0", expecting AssemblyResolve to fire. Surprisingly the CLR happily loads version 1.0.0.0 and fires no events.
Does anyone have a simple and working way to load a specific version of an assembly at runtime?
EDIT:
Thanks for all the answers so far. I haven't gotten it working yet the way I'd like, so your help is still needed. What I did get working was the AssemlyResolve event, like this:
int loadedAssemblies = getAsmCount(); // = 18
// LOAD V1.1 *UNREFERENCED*
var asm1_1 = Assembly.Load("_MyAssembly"); // AssemblyResolve fires behind the scene...
loadedAssemblies = getAsmCount(); // = 19
// USE V1.0 *REFERENCED IN VS SOLUTION*
// Note: seems that this Type's assembly has already been loaded!
var asm1_0 = new Class1().GetType().Assembly;
loadedAssemblies = getAsmCount(); // = 19
It seems that I have 18 assemblies loaded coming this piece of code, and to my surprise Class1 Type's Assembly (called MyAssembly, version 1.0.0.0) has already been loaded. That Assembly is referenced in visual studio normally.
When I manually load v1.1.0.0 of the same assembly, I need to use a little trick, a misspelled name, with underscore to get the AssemblyResolve event firing. Then it loads and I have 19 assemblies loaded, MyAssembly two times, once for v1.0.0.0 and once for 1.1.0.0. All fine except using 1.1.0.0. is a pain, I need to use reflection for that.
What I'd like to have to have direct access to v1.1 (the manually loaded one) of MyAssembly with this command:
var class1 = new Class1();
But now CLR gives me v1.0, the one referenced in visual studio.
How to fix this?
EDIT 2:
This question ended up morping too much, I made a compacter question here: New instance from a manually loaded assembly
you can load a specific assembly from a specific directory using:
Assembly.LoadFrom(string path)
and learn more about it here
now, you said it's your assembly, then if you decided to use reflection you can put it in a specific place (using to post-build for example to move it there) and in that way you don't have to change your code much. you can also investigate the location in order to know what files are there and load them and no loading writing the whole path hard-coded
Directory.GetFiles(string folderPath)
and then
foreach(string curr in filePaths)
{
Assembly.LoadFrom(curr )
}
You should check that there is no assembly already loaded with the same name as the one you want to load. That will prevent the loading of the second assembly.
If that isn't the case, you could use AssemblyResolve to get the assembly when .NET can't resolve it itself.
Here a small sample console app:
static void Main(string[] args)
{
AppDomain.CurrentDomain.AssemblyLoad += CurrentDomain_AssemblyLoad;
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
string aname = "MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
var asm = Assembly.Load(aname);
Console.ReadKey();
}
static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
Console.WriteLine("Resolving " + args.Name);
return Assembly.LoadFrom(#"C:\path\MyAssembly.6.0.dll");
}
static void CurrentDomain_AssemblyLoad(object sender, AssemblyLoadEventArgs args)
{
Console.WriteLine("Loading " + args.LoadedAssembly.FullName);
}
When you disable the two event handlers, you will see no assembly can be loaded. If you enable it, you will see it uses the assembly you provided.

"Could not load file or assembly 'System.Core, Version=2.0.5.0,..." exception when loading Portable Class Library dynamically

First of all I need to emphasize that this is slightly different question than the one in this thread. Additionally, installing KB2468871 doesn't help.
I tried to simplify this problem as much as possible. In general it about loading PCL assemblies in Desktop application with Assembly.LoadFile(...).
Let's say there is a .NET 4.0 Console Application (called "C"). It references .NET 4.0 assembly (called "N4") and PCL assembly (called "PCL").
where N4 looks like this:
using System.Linq;
namespace N4
{
public class ClassInN4
{
public static string Greet()
{
return new string(
"hello from N4"
.ToCharArray()
.Select(char.ToUpper)
.ToArray()
);
}
}
}
PCL looks like this:
using System.Linq;
namespace PCL
{
public class ClassInPCL
{
public static string Greet()
{
return new string(
"hello from pcl"
.ToCharArray()
.Select(char.ToUpper)
.ToArray()
);
}
}
}
and C look like this:
using System;
using System.IO;
using System.Reflection;
using N4;
using PCL;
namespace C
{
internal class Program
{
private static void Main(string[] args)
{
Test();
Console.ReadLine();
}
private static void Test()
{
Test("N4", ClassInN4.Greet);
Test("PCL", ClassInPCL.Greet);
}
private static void Test(
string title,
Func<string> generator)
{
try
{
Console.WriteLine(
"{0}: {1}", title, generator());
}
catch (Exception e)
{
Console.WriteLine(
"{0}: {1} -> {2}", title, e.GetType(), e.Message);
}
}
}
}
When you run this application you get absolutely correct results:
N4: HELLO FROM N4
PCL: HELLO FROM PCL
Let's add AssemblyResolve event to CurrentDomain in Program.Main:
AppDomain.CurrentDomain.AssemblyResolve += (_, a) => {
var fileName = Path.GetFullPath(
new AssemblyName(a.Name).Name + ".data");
Console.WriteLine("Probing '{0}'", fileName);
return
File.Exists(fileName)
? Assembly.LoadFile(fileName)
: null;
};
So, what it does if assembly cannot be found it tries to load it from ".data" file.
Let's go application folder and rename "N4.dll" to "N4.data" and run "C.exe".
Probing 'C:\xxx\C\bin\Debug\N4.data'
N4: HELLO FROM N4
PCL: HELLO FROM PCL
So it goes through AssemblyResolve and finally loads "N4.data" and works as good as original.
Let's revert "N4.data" to "N4.dll" and rename "PCL.dll" to "PCL.data" and...
Probing 'C:\xxx\C\bin\Debug\PCL.data'
N4: HELLO FROM N4
Probing 'C:\xxx\C\bin\Debug\System.Core.data'
Probing 'C:\xxx\C\bin\Debug\System.Core.data'
Probing 'C:\xxx\C\bin\Debug\System.Core.data'
PCL: System.IO.FileNotFoundException -> Could not load file or assembly 'System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes' or one of its dependencies. The system cannot find the file specified.
Please note that PCL assembly was loaded just fine, the problem is, it only can't find its dependencies (System.Core) anymore.
It's like Assembly.LoadFile(fileName) is-a no-no if loaded assembly is portable.
Did anyone have this problem? Did anyone solved this problem?
You can find all files here.
EDIT:
Thanks to leppie for forcing me to check other options. I actually wanted to be sure that I'm not lying while I answer "Yeah, yeah, I tried". Apparently it was worth checking.
From Suzanne Cook's .NET CLR Notes:
Be careful - these aren't the same thing.
LoadFrom() goes through Fusion and can be redirected to another assembly at a different path but with that same identity if one is already loaded in the LoadFrom context.
LoadFile() doesn't bind through Fusion at all - the loader just goes ahead and loads exactly* what the caller requested. It doesn't use either the Load or the LoadFrom context.
You can return the System.Core assembly of your platform (e.g. version 4.0.0.0 for .NET Framework 4.0) from the AssemblyResolve event, when asked for the 2.0.5.0 version.
I am loading all my referenced assemblies stored as resources via Load(byte[]), which also fails to resolve the 2.0.5.0 assembly, and I retrieve both System and System.Core from AppDomain.CurrentDomain.GetAssemblies().
I think you are getting these issues because:
You're getting an exception because you haven't got the latest .NET updates.
http://www.paraesthesia.com/archive/2013/01/21/using-portable-class-libraries-update-net-framework.aspx
Take note of the WSUS part - you may think you have the latest updates, but you don't cause your WSUS server is out of date.
This patch may help, but you're better just to get all the .net updates:
http://support.microsoft.com/kb/2468871
(from a comment above)
Try LoadFrom(...) rather than LoadFile(...) / Load(byte[]) and see if that fixes your issue? :)
I had the same problem and ended up with the following solution: invoke the following code before dynamically loading the PCL assembly.
Assembly.Load("System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes");
Assembly.Load("System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes");
If any other dependency is missing when you load your PCL assembly, you just need to add a line to code above.
For some strange and ununderstandable reason, it works.

CurrentDomain.AssemblyResolve not being able resolve 'some' assemblies

After finding the answer my last question on assembly resolving ( AppDomain.CurrentDomain.AssemblyResolve asking for a <AppName>.resources assembly? ) now i'm able to embed references assemblies on my program except that this does not work some references somehow.
First of all i setup my assembly resolver at the very first entrance of my Program.cs
// attach our embedded assembly loader.
AppDomain.CurrentDomain.AssemblyResolve += AssemblyManager.Instance.Resolver;
Here's my actual resolver;
public Assembly Resolver(object sender, ResolveEventArgs args)
{
AssemblyName askedAssembly = new AssemblyName(args.Name);
lock (this)
{
Assembly assembly;
string resourceName = string.Format("Assets.Assemblies.{0}.dll", askedAssembly.Name);
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
{
if (stream == null)
{
LogManager.Instance.Write(LogMessageTypes.Fatal, string.Format("Can not resolve asked assembly: {0}", askedAssembly.Name));
MessageBox.Show(i18n.CanNotLoadRequiredAssembliesMessage, i18n.CanNotLoadRequiredAssembliesTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
Environment.Exit(-1);
}
byte[] assemblyData = new byte[stream.Length];
stream.Read(assemblyData, 0, assemblyData.Length);
assembly = Assembly.Load(assemblyData);
}
LogManager.Instance.Write(LogMessageTypes.Trace, "Loaded embedded assembly: " + askedAssembly.Name);
return assembly;
}
}
Now my program references these libraries assemblies.
Esent.Collections.dll
Esent.Interop.dll
HtmlAgilityPack.dll
Ionic.Zip.Reduced.dll
System.Windows.Forms.Calendar.dll
AxInterop.ShockwaveFlashObjects
Interop.ShockwaveFlashObjects
irrKlang.NET4.dll
ikpMP3.dll
Nini.dll (SOLVED)
With my resolver above; i can embed Esent.Collections, Esent.Interop, HtmlAgilityPack, Ionic.Zip.Reduced,System.Windows.Forms.Calendar,AxInterop.ShockwaveFlashObjects,Interop.ShockwaveFlashObjects and resolve those on run-time.
The problem arrives with irrKlang.NET.4, Nini and ShockwaveFlash assemblies in which if i try to embed these assemblies and try to resolve them at runtime i'm having problems.
For irrKlang i can understand the problem as irrKlang.NET4 assembly references unmanaged ikpMP3.dll which i can't find on it's own.
For the Nini.dll, actually i can embed this assembly and using VS debug/release configurations runned it just works okay but when i startup the program on my own from the explorer, the program just refuses to startup (with no errors or any bit of info).
Any help appreciated.
Update
Now, thanks Marc Gravell's answer i can load the Nini.dll.
For the irrKlang part, as irrKlang.NET4.dll is a managed assembly which requires ikpMp3.dll -- an unmanaged one --, if i try to resolve irrKlang.NET4.dll on run-time it can access its required dependency ikpMp3. Is there work-around for this?
A common problem here is to use the types before you have chance to register the assembly-resolve event. In particular, note that the system must be able to JIT a method before it can start running a method - including Main().
So if your entry-point (Main()) does the event hooking and also talks to the types in question, it will attempt to resolve the types (for JIT) before or has chance to subscribe.
Do the minimum in main; move the "real" code to another method, that is only invoked once the event is definitely subscribed.
For example:
static void Main() {
SubscribeAssemblyResolver();
ExecuteApplication();
}
In extreme cases you may even need to use MethodImplAttribute to disable inlining of the methods above.

Categories