Reputation: 359
I'm using Reflection, and ilGenerator, to create a .Exe, that calls a method from a DLL.
My problem is when it is an instance method, I have to put in stack the instance before calling the method. Therefore I have a method in C#, that creates and returns this instance. It is throwing System.MethodAccessException
.
My question is, is this even possible? How does it work? By doing this in IL, il.Emit(Opcodes.call, methodInfo)
, in the call that creates the .exe, when in runtime, how does it know what method to call? Does the method that I want to call, go to the .exe assembly? I'm very confused by this.
I go to the DLL, get the type, get the MethodInfo
that I want to call.
I create a new Assembly->AssemblyBuilder->ModuleBuilder->TypeBuilder this new type that I am creating is extending the Type from the DLL:
TypeBuilder tb = mb.DefineType("TypeApp" + typeName, baseType.Attributes, DLLType);
I create the MethodBuilder
to be the entry point of the new type:
MethodBuilder metb = tb.DefineMethod("Main", MethodAttributes.Public |
MethodAttributes.Static, typeof(void), argsArray);
ab.SetEntryPoint(metb);
Then I generate IL for the Main
method:
ILGenerator il = metb.GetILGenerator();
il.Emit(OpCodes.Call, callcreateInstanceMethodInfo);
The IL continues, but I don't fully understand this so far so...
Then I create the .exe
tb.CreateType();
ab.Save(typeName + methodName + ".exe");
Upvotes: 3
Views: 381
Reputation: 2856
It is throwing
System.MethodAccessException
.
Are you trying to call a method that is not normally visible to the type you are generating (calling a private or internal method, calling a protected method in a class you don't inherit from). I believe it is possible by disabling verification, but that increases the security requirements of the code which is a problem if you need to run in a partial trust environment.
in the call that creates the .exe, when in runtime, how does it know what method to call?
The emitted IL contains a 4-byte metadata token, this is essentially a reference to a record in one of the metadata tables in the generated module (either the MethodDef or MemberRef table). If it's MethodDef token, then it's a direct reference to the methods definition, if it's a MemberRef token then it will provide enough information to identify the correct assembly/class/method to call.
The code you show generating the IL, indicates that you using the call opcode. If you are calling a virtual method, then you should use callvirt instead (although you can use call for non-abstract methods, it will result in calling the specific implementation ... even if it was overridden, this can be unexpected and I read somewhere that there were added security requirements for using call on a virtual method of another object).
Upvotes: 2