I load an assembly
private System.Reflection.Assembly;
object myData;
myAssembly = System.Reflection.Assembly.LoadFile("C:\\CrystalDecisions.CrystalReports.Engine.dll");
then i create an instance.
myData=myAssembly.CreateInstance("CrystalDecisions.CrystalReports.Engine.ReportDocument", true);
this myData always returns null, any thought why it is returning null where as myAssembly has the assembly information and its public key token?
try something like the following below..
// dynamically load assembly from file Test.dll
Assembly myData = Assembly.LoadFile(#"C:\CrystalDecisions.CrystalReports.Engine.dll");
// get type of class Calculator from just loaded assembly
Type myData = myData.GetType("CrystalDecisions.CrystalReports")
// create instance of class Calculator
object myDataInstance = Activator.CreateInstance(myData);
Reflection Examples C#
Related
I have a class library in which I load dynamic assemblies. How can I load these assemblies using the new MetaDataLoadContext and MetaDataAssemblyResolver?
Code:
// Retrieve the domain assembly used by the compilation
Assembly baseAssembly = typeof(MyType).Assembly;
// Retrieve the location of the assembly and the referenced assemblies used by the domain
AssemblyName[] baseAssemblyReferences = baseAssembly.GetReferencedAssemblies();
var paths = new List<string>();
foreach (var item in baseAssemblyReferences)
{
paths.Add(item.Name + ".dll");
}
paths.Remove("mscorlib.dll");
paths.Remove("System.Runtime.dll");
paths.Remove("netstandard.dll");
paths.Remove("System.Core.dll");
paths.Remove("System.dll");
// Create PathAssemblyResolver that can resolve assemblies using the created list.
var resolver = new PathAssemblyResolver(paths);
var mlc = new MetadataLoadContext(resolver, baseAssmebly.GetName().Name);
I am getting an error:
Could not find assembly 'MYAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. Either explicitly load this assembly using a method such as LoadFromAssemblyPath() or use a Metadata AssemblyResolver that returns a valid assembly
Is this possible if not could some one please explain how i could implement this to work?
So i have a C# Application and a folder with it called modules, so files:
Application.exe
modules/
Application.Handler.ModuleName.dll
So inside the DLL it has the namespace Application.Handle containing the type ModuleName and ModuleName extends Handler that is implemented in Application.exe so to compile requires Application.exe as a reference.
Inside my host application i have:
string[] dirs = Directory.GetFiles(#"modules/", "Application.Handler.*.dll");
foreach(string filePath in dirs)
{
Assembly.LoadFile(new FileInfo(filePath).FullName);
string fileName = filePath.Split('/').Last();
string typeAssemblyName = fileName.Replace(".dll", "");
string typeName = typeAssemblyName.Split('.').Last();
}
But i'm unsure if i can implement the types from the strings i thought i could with Activator.CreateInstance but i'm not sure if I'm doing it correctly or if the way I'm trying to implement it works?
UPDATE
I might not have been clear but effectively what i need to do is
Application.Handler handler = new Application.Handler.ModuleName() Where Application.Handler.ModuleName in php it's done like below i thought there would be a system that returns an object of the type given in the string. if it's not there throw an exception
$className = "\Application\Handler\ModuleName";
$instance = new $className();
I have also tried using the Unwrap system that #rene suggested
Assembly asm = Assembly.LoadFile(new FileInfo(filePath).FullName);
string fileName = filePath.Split('/').Last();
string typeAssemblyName = fileName.Replace(".dll", "");
string typeName = typeAssemblyName.Split('.').Last();
FrameHandler fh;
fh = (FrameHandler)Activator.CreateInstance(asm.FullName, typeAssemblyName).Unwrap();
fh.RegisterHandlers();
using this method where i give it the Assembly name it gives me a FileNotFoundException and without the Assembly name i get TypeLoadException but it must be loading the manifest of the assembly as Application.Handler.ModuleName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
You just need a handle to the type, so you'll need the assembly path and the type's full name.
var assy = Assembly.LoadFile("...");
var type = assy.GetType("...");
var obj = Activator.CreateInstance(type);
Assembly myDll = Assembly.LoadFrom("D:\\ClassLib.dll, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=173d654960d26d29");
I am getting the exception saying "Could not load the assembly"
Please help me here.
Refer to the MSDN documentation for loading assembly. Try giving just the assembly path as an argument to this method and it would work as per the example in documentation.
In order to check the authenticity of your assembly what you can do is following:
string filePath = "C:/path/to/file.dll";
Assembly assembly = Assembly.LoadFrom(filePath);
Module module = assembly.GetModules().First();
X509Certificate certificate = module.GetSignerCertificate();
if (certificate == null)
{
// file is not signed.
}
As a matter of fact once your assembly is loaded you have most of the properties such as version number etc. in the assembly object.
Based on this article on MSDN website, there is a better way to check validity.
Paste this 2 line of code to the top of your relevant class.
[DllImport("mscoree.dll", CharSet = CharSet.Unicode)]
static extern bool StrongNameSignatureVerificationEx(string wszFilePath, bool fForceVerification, ref bool pfWasVerified);
Load your assembly
var filePath = "C:/whatever.dll";
var assembly = Assembly.LoadFrom(filePath);
Set the last 2 parameters regarding to your needs and call the function.
Little helper table
var alertMessage = "Spoofed!";
var isValid = StrongNameSignatureVerificationEx(filePath, ....);
if (!isValid)
throw new FileNotFoundException(alertMessage, filePath);
Note: As far as I know there is no managed version of this. So, be thread-safe when you use this function!
you can load the Assembly as follows
string path = #"D:\ClassLib.dll";
Assembly assembly = Assembly.LoadFrom(path);
More Sources here
During my studies of reflection, I have encountered the .net module.
I understand that means I can compile a single class as .net module (correct me if I wrong) then load this compiled .net module using Assembly.LoadModule(string,byte[]).
I wrote a class that look like this:
using System;
using System.Text;
public class Mycs {
public static string GiveString(){
return "Hello World !";
}
}
and compiled it using the switch "/target:module" using this code:
CodeDomProvider CDP = CodeDomProvider.CreateProvider("CSharp");
CompilerParameters CP = new CompilerParameters();
CP.GenerateExecutable = false;
CP.CompilerOptions = "/target:module";
CP.OutputAssembly = FilePathText.Text.Replace(Strings.Right(FilePathText.Text, 3), ".netmodule");
string source = File.ReadAllText(FilePathText.Text);
CompilerResults RS = CDP.CompileAssemblyFromSource(CP, source);
I then retrieved the resulted file bytes:
byte[] b = File.ReadAllBytes(FilePathText.Text);
And finally I tried to load the module to the current executed assembly:
Module[] Modules = Assembly.GetExecutingAssembly().GetModules();
Module[] moduless = Assembly.GetExecutingAssembly().GetLoadedModules();
Module A = Assembly.GetExecutingAssembly().LoadModule(Modules[0].Name, b);
Whether I passed the Modules[0].Name or moduless[0].Name both cause this exception:
An unhandled exception of type 'System.ArgumentException' occurred in mscorlib.dll
Additional information: Invalid file name
Why do I get this invalid file name error?
You cannot load dynamically created module to an existing assembly, assemblies once compiled are immutable.
My best guess is that you need to use AssemblyBuilder.DefineDynamicModule() to create your classes in it. In this case you the type you created will be loaded automatically. or compile your classes as assemblies, not the modules, and load those assemblies dynamically using Assembly.LoadFile method.
How do I get a list of references in the parent assembly in C#. I'm thinking of a DLL that is loaded into another program, and the driver needs to use some of the parent assembly references in reflection and serialization. So far, I haven't tried anything as I'm not sure where to start.
It's pretty classic reflection issue, when you need to load an assembly and the assembly contains references, which are not referenced to the calling assembly.
Basically, you should load the assembly inside separate application domain.
e.g., you have a project ProxyDomain with a class ProxyType:
public class ProxyType : MarshalByRefObject
{
public void DoSomeStuff(string assemblyPath)
{
var someStuffAssembly = Assembly.LoadFrom(assemblyPath);
//Do whatever you need with the loaded assembly, e.g.:
var someStuffType = assembly.GetExportedTypes()
.First(t => t.Name == "SomeStuffType");
var someStuffObject = Activator.CreateInstance(someStuffType);
someStuffType.GetMethod("SomeStuffMethod").Invoke(someStuffObject, null);
}
}
And in your calling project, which contains a reference to ProxyDomain, you need to load the assembly, execute DoSomeStuff and unload the assembly resources:
public class SomeStuffCaller
{
public void CallDoSomeStuff(string assemblyPath)
{
AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
//Path to the directory, containing the assembly
setup.ApplicationBase = "...";
//List of directories where your private references are located
setup.PrivateBinPath = "...";
setup.ShadowCopyFiles = "true";
var reflectionDomain = AppDomain.CreateDomain("ProxyDomain", null, setup);
//You should specify the ProxyDomain assembly full name
//You can also utilize CreateInstanceFromAndUnwrap here:
var proxyType = (ProxyType)reflectionDomain.CreateInstanceAndUnwrap(
"ProxyDomain",
"ProxyType");
proxyType.DoSomeStuff(assemblyPath);
AppDomain.Unload(reflectionDomain);
}
}