Reflection TargetInvocationException error when charging DLL dynamically - c#

I need to load a DLL dynamically so I can compare two identical methods from different DLL version, without using Web-services.
I already did that on an other project, and it worked perfectly.
But the Dll I need to import is more complex now, it uses C++ dll reference etc.
Here is the part of code :
Type type1 = dll1.GetType("MyNamespace.MyClass");
var instance1 = Activator.CreateInstance(type1, "some string", "some string", "some string");
MethodInfo myMethod1 = type1.GetMethods().Where(X => X.Name == "myMethod").FirstOrDefault();
object retour1 = (object)myMethod1.Invoke(instance1, new object[] { fichier.FullName, dossier.FullName, null, false, null });
The last line of code return a "System.Reflection.TargetInvocationException"
apperently in "mscorlib.dll"
Since I am quite new to reflection, I do not really know what is happening, is this because of c++ dll, or did i forget something? The same code works on simpler DLL.
Maybe there is a better way to do this task, but as I cannot do the following :
Using myLib
Using myLib
I am stuck, any help would be very appreciated =)

Related

How to call a WCF service with incomplete service definition

I am trying to use a service created by somebody else. I have only the service dll. But the instructions provided to me are not complete. This is an example how to use the service but they missed the instantiation of the variable criteria. How can I figure out what type is the variable? . If possible, I prefer to solve the issue without decompiling the dll.
public static void GetData()
{
//ServiceReference1.ServicesClient client = null;
try
{
criteria.Settings = new CheckCall.CriteriaSettings();
CheckCall.Criteria criteria1 = new CheckCall.Criteria();
criteria1.Settings = new CheckCall.CriteriaSettings();
criteria1.AsgnType = CheckcallAssignTypeEnum.Driver;
criteria1.TractorNumber = "Tractor1";
criteria.Expressions = new List<CheckCall.CriteriaExpression>();
criteria.Expressions.Add(new CheckCall.CriteriaExpression
{
Conjuction = CriteriaSetting.ConjuctionEnum.OrOp,
Criteria = criteria1
});
}
catch(Exception ex)
{
Console.Write(ex);
}
}
You could use JetBrains .Net decompiler - dotPeek.(https://www.jetbrains.com/decompiler/)
Decompile the dll, then add the decompiled project to your solution and debug it. The only problem is wether you will receive a project that can be built after decompilation
If the decompilation is not an option/project has errors after decompilation - you can see the contents of the .dll via Object Browser. Find the .dll in the References, right click on it and choose "View in Object Browser". You will see the namespaces, classes and their methods of the .dll. Enter any of the property names of criteria object (Settings or Expressions) and Object Browser will filter everything out

DLL dependency not getting copied issue

I'm using VS2015 and have two projects where the child project references DapperExtensions (X--> Y--> DapperExtensions).
Now DapperExtensions seems to have implicit dependency on Dapper.
When I try and use code from Y in X, I get an error regarding Dapper.dll missing.
It seems with dlls being copied to project X debug folder, only DapperExtensions.dll is getting copied but Dapper.dll isn't.
Presumably related to the direct dependency issue identified in stackoverflow already :
Dll not copying to bin folder
So I created some dummy code to reference an arbitrary reference from Dapper but this doesn't seem to lead to the DLL getting copied as per existing suggestions in stackoverflow:
public static void Dummy()
{
Action<Type> noop = _ => { };
var dummy = typeof(Dapper.DbString);
noop(dummy);
}
The only thing I guess left is to add dappper dll reference directly to ProjectX which I really want to avoid.
Any ideas why the dummy reference thing doesn't work?

Need to process a dataset via dynamic runtime code in C#

I have been working with C# dynamic code for run time processes. My problem is I cannot seem to pass a dataset object to the dynamic code with out getting:
"Could not load file or assembly 'file:///C:\Users\mgallanx\AppData\Local\Temp\npbylo5z.dll' or one of its dependencies. The system cannot find the file specified."
Here is the simplest dataset processing string I am using:
mycodestring = "using System;
using System.Data;
namespace DaCodeNS
{
public static class DaCode
{
public static DataSet DaMethod( Dataset dsIn)
{
return dsIn;
}
}
}"
the calling method sets the parameters to add the System.dll and System.Data.dll, creates an Object[] mp to one element of sIn.
The call then is:
CompilerResults results = provider.CompileAssemblyFromSource (parameters, mycodestring);
var cls = results.CompiledAssembly.GetType ("DaCodeNS.DaCode");
var method = cls.GetMethod ("DaMethod", BindingFlags.Static | BindingFlags.Public);
return (DataSet) method.Invoke (null, mp);
It breaks at the GetMethod line.
I can get similar code passing integers around to play, but changing the return and passed to DataSet blows up. Any help is appreciated.
You're most likely not including all of the references needed to make your dynamic code compile/run. A simple way to find all the needed references would be to create a standa-alone project that just includes the code you're going to compile. Then look at the references you needed to add to the project to get it to compile/run.

Including an embedded resource in a compilation made by Roslyn

I'm attempting to include an embedded resource into a dll that I am compiling using Roslyn. I've found something that helped put me on the right track here.
However, when I create the dll using the following code:
const string resourcePath = #"C:\Projects\...\Properties\Resources.resources";
var resourceDescription = new ResourceDescription(
"Resources.resources",
() => File.OpenRead(resourcePath),
true);
var result = mutantCompilation.Emit(file, manifestResources: new [] {resourceDescription});
I find that it will pass all of the unit tests that I have created for the project except for those that rely on the Resources file.
The error I'm getting looks like the following:
System.Resources.MissingManifestResourceException ... Make sure "[Project].Properties.Resources.resources" was correctly embedded or linked into
assembly "[Project]" at compile time, or that all the satellite assemblies required are loadable and fully signed.
The dll is supposed to be signed, and when it is emitted by roslyn it comes out with the correct public key. Also, the Resource.resx is included in my project directly in the Properties folder.
I would appreciate any help anyone could provide.
Ok, so while I was looking for answers, I came across this web page where it was commented that the resource stream was null until the he added the namespace.
So after adding the namespace I got somehting like this
const string resourcePath = #"C:\Projects\...\Properties\Resources.resources";
var resourceDescription = new ResourceDescription(
"[namespace].Resources.resources",
() => File.OpenRead(resourcePath),
true);
var result = mutantCompilation.Emit(file, manifestResources: new [] {resourceDescription});
which runs exactly like you'd expect.

How to execute different statements based on the file version of a referenced dll?

I have a C# dll that references a 3rd party dll. There are different versions of the 3rd party dll.
As you might expect if the latest 3rd Party dll is present I want to use the new functionality if not I want to execute the old functionality.
I wasn't sure how to achieve this but I thought the first thing to try would be a simple if statement that decides which function to call.
So I find the assembly, get its location and hence its version info. (I need the file version as the product versions are the same).
Then a simple
if (version >= 3) do x() else do y()
When I execute the code on a machine with version 2 installed I get a MissingMethodException regarding x(). I thought I had made a stupid mistake but the logic was correct. The version is 2 so x(); should not be executed. I decided to remove the offending method and replace it with a throw new Exception(). The exception is not thrown and the code completes successfully.
Here is the danger - I am thinking that this is due to branch prediction. This is dangerous because it is not an area I have any knowledge of and therefore making assumptions is a dangerous thing.
So my questions are:
Am I tacking this problem the wrong way - is there a more obvious solution that I am missing?
or
Is there a way to disable branch prediction (if that is the cause) or to somehow enforce/flag the if condition as a point that must be executed before continuing.
Here is the code being executed:
On a machine with version 3 installed then it is fine.
On a machine with version 2 installed I get a MissingMethodException regarding method x().
It I removed the call to x(); and uncomment the throwing of the exception - no exception is thrown.
Relevant code:
Assembly assembly = System.Reflection.Assembly.GetAssembly(typeof(3rdPartyClass));
FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(assembly.Location);
if (fileVersionInfo.FileMajorPart >= 3)
{
// throw new Exception("aagghh");
x();
}
else
{
y();
}
Using reflection, it's possible to get a list of Methods available for a particular DLL (more specifically: Type).
You could use this methodinfo to dynamically invoke the method as specified in Vlad's solution.
In fact, you could leave out the version check and just try to find the intended method directly.
var methodX = assembly.GetType("sometype").GetMethod("X");
if (methodX != null)
{
methodX.Invoke(params);
}
else
{
assembly.GetType("sometype").GetMethod("Y").Invoke(otherParams);
}
Edit: This is not exactly what you want, but with this kind of reflection you can find the correct methods, also for your own assembly.
There is no "branch prediction": the runtime binding seems to happen as the method is executed.
So the workaround would be like this:
if (fileVersionInfo.FileMajorPart >= 3)
{
CallX();
}
else
{
CallY();
}
void CallX()
{
DependentClass.X();
}
void CallY()
{
DependentClass.Y();
}
However, anyway this seems to be a hack: you need to execute with the version of DLL you were linking against.
This is actually a more accurate answer :
Assembly assembly = System.Reflection.Assembly.GetAssembly(typeof(String));
FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(assembly.Location);
ObjectHandle oh = Activator.CreateInstanceFrom("AssemblyName.dll", "namespace.class");
object o = oh.Unwrap();
Type to = o.GetType();
if (fileVersionInfo.FileMajorPart >= 3)
{
to.InvokeMember("Method X", BindingFlags.InvokeMethod, null, o, null);
}
else
{
to.InvokeMember("Method Y", BindingFlags.InvokeMethod, null, o, null);
}

Categories