I've a WPF application that loads 3 different assembly which containts application extensions. I've added to the 3 projects the ModuleInit.Fody and for now just put a Console.WriteLine("module")
I load the assemblies with this piece of code
var files = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "MyApplication.Modules*.dll");
List<Assembly> assemblies = new List<Assembly>();
foreach (var file in files)
{
AssemblyName assamblyName = AssemblyName.GetAssemblyName(file);
var assembly = Assembly.Load(assamblyName); //this throw an exception
// AssemblyName name = new AssemblyName()
//var assembly = Assembly.LoadFrom(file);
assembly.GetTypes().First();
assemblies.Add(assembly);
}
What am I doing wrong?
Thanks
UPDATE1 you can find a demo here
A module initializer is run the first time any type from that assembly is used. NOT when the module is loaded
Related
Im trying to load assembly to my project from different folder out of root and also set a new domain for it. My goal is to load and unload during the run-time. All working fine when ddl files are in root of application, but once i put it in folder plugins im getting error file not found. I know there is a lot of topic like this but non of them cover all my needs and non of them work as excepted im afraid. It works once i loaded to current domain..
example code:
dllFileNames = Directory.GetFiles(path, "*.dll");
ICollection<Assembly> assemblies = new List<Assembly>(dllFileNames.Length);
AppDomain currentDomain = AppDomain.CurrentDomain;
Evidence asEvidence = currentDomain.Evidence;
AppDomainSetup aps = new AppDomainSetup
{
ApplicationBase = #"[root of application]",
PrivateBinPath = #"[Plugin folder]"
};
AppDomain myDomain = AppDomain.CreateDomain("Plugins",asEvidence,aps);
SimpleAssemblyLoader assemblyLoader = (SimpleAssemblyLoader)myDomain.CreateInstanceAndUnwrap(typeof(SimpleAssemblyLoader).Assembly.FullName, typeof(SimpleAssemblyLoader).FullName);
foreach (string dllFile in dllFileNames)
{
assemblyLoader.LoadFrom(dllFile);
}
var assemblyList = myDomain.GetAssemblies(); // in here getting error :( file not found for no reason.
System.IO.FileNotFoundException: 'Could not load file or assembly 'Name, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.'
public class SimpleAssemblyLoader : MarshalByRefObject
{
public void Load(string path)
{
ValidatePath(path);
Assembly.Load(path);
}
public void LoadFrom(string path)
{
ValidatePath(path);
Assembly.LoadFrom(path);
}
private void ValidatePath(string path)
{
if (path == null)
{
throw new ArgumentNullException("path");
}
if (!System.IO.File.Exists(path))
{
throw new ArgumentException(string.Format("path \"{0}\" does not exist", path));
}
}
}
Set AppDomain.BaseDirectory to your plugins folder.
Or register AppDomain.AssemblyResolve event to resolve missing assemblies.
For .Net Core programing, take a look at AssemblyLoadContext class
I need generate typescript files from some of my C# classes after build.
I created dotnet cli tool and added post-build event
dotnet tsgenerator "$(TargetPath)"
where $(TargetPath) is macros pointing, for example, D:\Test\bin\Release\netcoreapp2.0\my.dll
Next, i tried to load assembly next way:
public static void Main(string[] args)
{
var dllPath = args[0]; // "D:\Test\bin\Release\netcoreapp2.0\my.dll"
var assembly = Assembly.LoadFile(dllPath);
var types = assembly.GetExportedTypes(); // Throws exception
}
But i got ReflectionTypeLoadException that says Could not load file or assembly for some references assemblies (for example, Microsoft.AspNetCore.Antiforgery).
How i can load assembly for .NET Core applications?
I'm found solution at github issue. Message by amits1995 and angelcalvasp.
I'm added <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> to my csproj and using this code to load assembly:
public static class AssemblyLoader
{
public static Assembly LoadFromAssemblyPath(string assemblyFullPath)
{
var fileNameWithOutExtension = Path.GetFileNameWithoutExtension(assemblyFullPath);
var fileName = Path.GetFileName(assemblyFullPath);
var directory = Path.GetDirectoryName(assemblyFullPath);
var inCompileLibraries = DependencyContext.Default.CompileLibraries.Any(l => l.Name.Equals(fileNameWithOutExtension, StringComparison.OrdinalIgnoreCase));
var inRuntimeLibraries = DependencyContext.Default.RuntimeLibraries.Any(l => l.Name.Equals(fileNameWithOutExtension, StringComparison.OrdinalIgnoreCase));
var assembly = (inCompileLibraries || inRuntimeLibraries)
? Assembly.Load(new AssemblyName(fileNameWithOutExtension))
: AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyFullPath);
if (assembly != null)
LoadReferencedAssemblies(assembly, fileName, directory);
return assembly;
}
private static void LoadReferencedAssemblies(Assembly assembly, string fileName, string directory)
{
var filesInDirectory = Directory.GetFiles(directory).Where(x => x != fileName).Select(x => Path.GetFileNameWithoutExtension(x)).ToList();
var references = assembly.GetReferencedAssemblies();
foreach (var reference in references)
{
if (filesInDirectory.Contains(reference.Name))
{
var loadFileName = reference.Name + ".dll";
var path = Path.Combine(directory, loadFileName);
var loadedAssembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(path);
if (loadedAssembly != null)
LoadReferencedAssemblies(loadedAssembly, loadFileName, directory);
}
}
}
}
Usage:
public static void Main(string[] args)
{
var dllPath = args[0]; // "D:\Test\bin\Release\netcoreapp2.0\my.dll"
var assembly = AssemblyLoader.LoadFromAssemblyPath(dllPath);
var types = assembly.GetExportedTypes(); // No exceptions
}
Well you are able to load assembly but GetTypes() and GetExportedTypes() depend on the public classes within that assembly, if they have external references you get this exception.
Answer:
This means the Types of that assembly depend on other assembly which the current .NetCore does not have access at the run time because it can not connect to other dependent assemblies
Solution:
Get dependencies of the DLL assemblies and compile all of them, then load each assembly iteratively to get all ExportedTypes (i.e publicly visible Types)
Code:
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using Microsoft.Extensions.DependencyModel;// add this nuget
class Program
{
static void Main(string[] args)
{
var asl = new AssemblyLoader();
var asm = asl.LoadFromAssemblyPath(#"C:\temp\Microsoft.AspNetCore.Antiforgery.dll");
try
{
var y = asm.GetExportedTypes();
Console.WriteLine(y);
}
catch (Exception e1)
{
Console.WriteLine("Got exception at first attempt of GetExportedTypes ");
Console.WriteLine("\t*********" + e1.Message + "**************");
var deped = asl.CallForDependency(asm.GetName());
try
{
Console.WriteLine("\n" + deped.ToString());
Console.WriteLine("----------All Exported Types------------");
foreach (var item in deped.ExportedTypes)
{
Console.WriteLine(item);
}
}
catch (Exception e2)
{
Console.WriteLine("Got exception at second attempt of GetExportedTypes ");
Console.WriteLine("\t*********" + e2.Message + "**************");
}
}
Console.ReadLine();
}
}
public class AssemblyLoader :AssemblyLoadContext
{
protected override Assembly Load(AssemblyName assemblyName)
{
var deps = DependencyContext.Default;
var res = deps.CompileLibraries.Where(d => d.Name.Contains(assemblyName.Name)).ToList();
var assembly = Assembly.Load(new AssemblyName(res.First().Name));
return assembly;
}
public Assembly CallForDependency(AssemblyName assemblyName)
{
return this.Load(assemblyName);
}
}
Output :
Got exception at first attempt of GetExportedTypes
*********Could not load file or assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. An operation is not legal in the current state. (Exception from HRESULT: 0x80131509)**************
Microsoft.AspNetCore.Antiforgery, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
----------All Exported Types------------
Microsoft.Extensions.DependencyInjection.AntiforgeryServiceCollectionExtensions
Microsoft.AspNetCore.Antiforgery.AntiforgeryOptions
Microsoft.AspNetCore.Antiforgery.AntiforgeryTokenSet
Microsoft.AspNetCore.Antiforgery.AntiforgeryValidationException
Microsoft.AspNetCore.Antiforgery.IAntiforgery
Microsoft.AspNetCore.Antiforgery.IAntiforgeryAdditionalDataProvider
Microsoft.AspNetCore.Antiforgery.Internal.AntiforgeryFeature
Microsoft.AspNetCore.Antiforgery.Internal.AntiforgeryOptionsSetup
Microsoft.AspNetCore.Antiforgery.Internal.AntiforgerySerializationContext
Microsoft.AspNetCore.Antiforgery.Internal.AntiforgerySerializationContextPooledObjectPolicy
Microsoft.AspNetCore.Antiforgery.Internal.AntiforgeryToken
Microsoft.AspNetCore.Antiforgery.Internal.BinaryBlob
Microsoft.AspNetCore.Antiforgery.Internal.CryptographyAlgorithms
Microsoft.AspNetCore.Antiforgery.Internal.DefaultAntiforgery
Microsoft.AspNetCore.Antiforgery.Internal.DefaultAntiforgeryAdditionalDataProvider
Microsoft.AspNetCore.Antiforgery.Internal.DefaultAntiforgeryTokenGenerator
Microsoft.AspNetCore.Antiforgery.Internal.DefaultAntiforgeryTokenSerializer
Microsoft.AspNetCore.Antiforgery.Internal.DefaultAntiforgeryTokenStore
Microsoft.AspNetCore.Antiforgery.Internal.DefaultClaimUidExtractor
Microsoft.AspNetCore.Antiforgery.Internal.IAntiforgeryFeature
Microsoft.AspNetCore.Antiforgery.Internal.IAntiforgeryTokenGenerator
Microsoft.AspNetCore.Antiforgery.Internal.IAntiforgeryTokenSerializer
Microsoft.AspNetCore.Antiforgery.Internal.IAntiforgeryTokenStore
Microsoft.AspNetCore.Antiforgery.Internal.IClaimUidExtractor
Reference and explanation on ReflectionTypeLoadException:
Assembly.GetTypes Method ()
ReflectionTypeLoadException
The assembly contains one or more types that cannot be loaded. The
array returned by the Types property of this exception contains a Type
object for each type that was loaded and null for each type that could
not be loaded, while the LoaderExceptions property contains an
exception for each type that could not be loaded.
Remarks
The returned array includes nested types.
If the GetTypes method is called on an assembly and a type in that
assembly is dependent on a type in an assembly that has not been
loaded (for example, if it derives from a type in the second
assembly), a ReflectionTypeLoadException is thrown. For example, this
can happen if the first assembly was loaded with the
ReflectionOnlyLoad or ReflectionOnlyLoadFrom methods, and the second
assembly was not loaded. It can also happen with assemblies loaded
using the Load and LoadFile methods if the second assembly cannot be
located when the GetTypes method is called.
Note
If a type has been forwarded to another assembly, it is not included
in the returned array. For information on type forwarding, see Type
Forwarding in the Common Language Runtime.
Linked :
How to load assemblies located in a folder in .net core console app
How to dynamically load assemblies in dotnet core
Try the LoadFrom method for loading in the assembly, rather than LoadFile:
public static void Main(string[] args)
{
var dllPath = args[0]; // "D:\Test\bin\Release\netcoreapp2.0\my.dll"
var assembly = Assembly.LoadFrom(dllPath);
var types = assembly.GetExportedTypes(); // Throws exception
}
You will also need to add the same references that are in the ddl file to your current project, so that the types are defined.
I want to use MEF to achieve dependency injection. However, when trying to load all the different .dll files it always runs into the an System.Reflection.ReflectionTypeLoadException: The classes in the module cannot be loaded. This occurs when trying to load "Microsoft.AspNet.Identity.Owin.dll".
I'm trying to do this on a mac, using the mono compiler and the target framework set at: .NET Framework 4.5.2
#region Constructor
public ModuleConfigurationCatalog()
{
var assemblyUri = new Uri(Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath));
var assemblyDir = assemblyUri.LocalPath;
var allFiles = Directory.EnumerateFiles(assemblyDir, "*.*", SearchOption.AllDirectories);
var assemblies = allFiles.Where(f => f.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) || f.EndsWith(".exe", StringComparison.OrdinalIgnoreCase)).Distinct();
_catalog = new AggregateCatalog();
foreach (var assembly in assemblies)
{
var assemblyCatalog = new AssemblyCatalog(assembly);
if (assemblyCatalog.Parts.ToList().Count > 0)
{
_catalog.Catalogs.Add(assemblyCatalog);
}
}
}
#endregion
breakpoint information
Stacktrace
You're probably missing a dependency of the Microsoft.AspNet.Identity.Owin.dll assembly. Make sure all of its dependencies exist in the same folder. (Or maybe load it from the GAC if it exists there... not sure how to do that with MEF, though.)
I have runtime-compiled assembly that references another assembly (DynLoadedAssembly) that is located in specific path and loaded dynamically. When I execute runtime-compiled assembly, I get an error: System.IO.FileNotFoundException Could not load file or assembly 'DynLoadedAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies.
Check out code:
public string Run()
{
var text = #"
using DynLoadedAssembly;
public class DynClass
{
public static string Evaluate()
{
return new SomeClass().Do();
}
}";
var dynAssemblyPath = #"c:\path\to\DynLoadedAssembly.dll";
Assembly.LoadFile(dynAssemblyPath);
var tree = SyntaxFactory.ParseSyntaxTree(text);
var compilation = CSharpCompilation.Create(
"calc",
options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary),
syntaxTrees: new[] { tree },
references: new[]
{
MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
MetadataReference.CreateFromFile(dynAssemblyPath)
}
);
Assembly compiledAssembly;
using (var stream = new MemoryStream())
{
var compileResult = compilation.Emit(stream);
compiledAssembly = Assembly.Load(stream.GetBuffer());
}
Type dynClass = compiledAssembly.GetType("DynClass");
MethodInfo evaluate = dynClass.GetMethod("Evaluate");
return evaluate.Invoke(null, null).ToString();
}
Here SomeClass is defined in DynLoadedAssembly that loaded dymanically from dynAssemblyPath.
If I place DynLoadedAssembly into execution assembly folder - then it works fine.
Other workarounds are:
specify probing (https://msdn.microsoft.com/en-us/library/823z9h8w(v=vs.110).aspx) element in App.config
use AssemblyResolve event handler
But I want to load referenced assembly dynamically. So my questions are:
Why "Step 2: Checking for Previously Referenced Assemblies" (https://msdn.microsoft.com/en-us/library/yx7xezcf(v=vs.110).aspx#step2) failed? Why execuded code do not see DynLoadedAssembly library in current domain?
How to make my compiled assembly find previosly loaded assembly in current domain?
I am attempting to create a PCL assembly using Roslyn (Microsoft.CodeAnalysis).
I'm referencing PCL assemblies located at "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETPortable\v4.5\Profile\Profile259". Here is my code that compiles the actual assembly.
var assemblyName = string.Concat("ODataHQ.SDK.", accountKey, ".dll");
var source = GenerateAccountSource(accountKey, workspace);
var assemblyInfoSource = GetAssemblyInfo(assemblyName);
var assemblyTree = CSharpSyntaxTree.ParseText(assemblyInfoSource);
var tree = CSharpSyntaxTree.ParseText(source);
// Lets add PCL framework assemblies.
var frameworkFiles = new[] {"mscorlib.dll", "Microsoft.CSharp.dll", "System.dll", "System.Core.dll", "System.Runtime.dll"};
var references = frameworkFiles
.Select(file => Path.Combine(Settings.PCLProfilePath, file))
.Select(fullPath => MetadataReference.CreateFromFile(fullPath))
.Cast<MetadataReference>()
.ToList();
// Lets add third-party dependent assemblies.
references.AddRange(Directory.GetFiles(Settings.SDKDependencyPath, "*.dll")
.Select(file => MetadataReference.CreateFromFile(file)));
var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);
var compilation = CSharpCompilation.Create(assemblyName, new [] { assemblyTree, tree }, references, options);
var ms = new MemoryStream();
var result = compilation.Emit(ms);
if (result.Success)
{
// Reset stream position to read from beginning.
ms.Position = 0;
return ms;
}
// Destroy memory stream since it didn't compile successfully.
ms.Dispose();
var firstError = result.Diagnostics
.Where(d => d.Severity == DiagnosticSeverity.Error)
.Select(d => d.GetMessage())
.FirstOrDefault();
throw new CompilationException(firstError);
Here is my GetAssemblyInfo method:
private string GetAssemblyInfo(string assemblyName)
{
return #"using System.Reflection;
using System.Runtime.Versioning;
[assembly: AssemblyTitle(""" + assemblyName + #""")]
[assembly: AssemblyVersion(""1.0.*"")]
[assembly: AssemblyFileVersion(""1.0.*"")]
[assembly: TargetFramework("".NETPortable,Version=v4.5,Profile=Profile259"", FrameworkDisplayName="".NET Portable Subset"")]";
}
I take the assembly that is generated and save it to disk. Then reference it in another console app project. However, when I run the console app and try to use a type from the dynamically generated PCL assembly, I get the following error.
An unhandled exception of type 'System.IO.FileNotFoundException' occurred in mscorlib.dll
Additional information: Could not load file or assembly 'ODataHQ.SDK.dvester.dll, Version=1.0.5635.36199, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
Can someone help me figure out what's going wrong?
Check the FusionLog property of the exception (you may need to enable that in the registry).
This will tell you why it failed.