我可以访问这样的函数体中间语言:
byte[] ilCodes = NestedFooInfo.GetMethodBody().GetILAsByteArray();
我能够修改其 IL 代码,以便在执行方法主体之前调用名为 OnChangeField
的以下方法:
public static void OnChangeField()
{
Console.WriteLine("VICTORY");
return;
}
到目前为止我是这样做的:
我定义了我要调用的方法的调用指令:
MethodInfo OnStfld = typeof(MethodBoundaryAspect).GetMethod("OnChangeField");
byte[] callIL = new byte[5];
callIL[0] = (byte)OpCodes.Call.Value;
callIL[1] = (byte)(OnStfld.MetadataToken & 0xFF);
callIL[2] = (byte)(OnStfld.MetadataToken >> 8 & 0xFF);
callIL[3] = (byte)(OnStfld.MetadataToken >> 16 & 0xFF);
callIL[4] = (byte)(OnStfld.MetadataToken >> 24 & 0xFF);
请注意,OnChangeField 位于 MethodBoundaryAspect 类中。此类位于正在编辑的方法的程序集之外。
这就是我改变原始(NestedFoo(...)
)方法主体的方法:
byte[] ilCodes = NestedFooInfo.GetMethodBody().GetILAsByteArray();
InjectionHelper.UpdateILCodes(NestedFooInfo, callIL.Concat(ilCodes).ToArray());
我得到一个:
System.BadImageFormatException: 'Index not found. (Exception from HRESULT: 0x80131124)'
但是仅如果 Hook 方法OnChangeField
位于执行程序集之外(或者我是这么理解的)。如果我将 OnChangeField
移动到与 NestedFoo 相同的类中或 NestedFoo
程序集的另一个类中,则它可以正常工作。
我知道元数据 token 指向无效的内存位置。有办法改变吗?
这里的引用资料是: 更改后的方法的方法体如下所示:
public class ExceptionHandlingService : IExceptionHandlingService
{
public static string var1 = "initialValue";
public static string Var2 { get; set; } = "initialValue";
public string var3 = "initialValue";
public string Var4 { get; set; } = "initialValue";
public string NestedFoo(SampleClass bar)
{
var1 = "value set in NestedFoo()";
Var2 = "value set in NestedFoo()";
var3 = "value set in NestedFoo()";
Var4 = "value set in NestedFoo()";
AddPerson("From", "NestedFoo", 2);
return Foo();
}
[...]
}
以及我如何调用改变的方法:
var a = new ExceptionHandlingService();
var b = new SampleClass("bonjour", 2, 3L); // Not really relevant
a.NestedFoo(b);
对于那些想知道魔法发生在哪里的人
InjectionHelper.UpdateILCodes(NestedFooInfo, newIlCodes);
你可以检查 this link它展示了如何在运行时编辑 Il 代码。
最佳答案
您需要将记录添加到 MemberRef
以及连续的 TypeRef
或 TypeSpec
元数据表中,以包含对类型的引用并引用这些标记。这还涉及正确编写签名 blob。
请参阅 ECMA-335 的第 II 部分 22.38、22.25
关于c# - 如何在 MSIL 中调用正在执行的程序集之外的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64891113/