【发布时间】:2016-08-29 19:23:54
【问题描述】:
我试图在运行时替换插件加载器中的方法(如Bukkit for Minecraft)。在这种情况下,我无法直接修改程序集文件。整个目的是能够判断方法何时被调用。并在必要时取消它们。加载插件后,我运行以下代码:
public static void PluginLoaded()
{
replace();
}
public static void replace()
{
MethodInfo oldMethod, newMethod;
oldMethod = typeof(<other assembly>).GetMethod("<method name>", BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic,null,new Type[]{typeof(ushort)},null);
newMethod = typeof(NewEvents).GetMethod("<method name>", BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(ushort) }, null);
RuntimeHelpers.PrepareMethod(oldMethod.MethodHandle);
RuntimeHelpers.PrepareMethod(newMethod.MethodHandle);
ReplaceInner(oldMethod, newMethod);
}
static void ReplaceInner(MethodInfo methodToReplace, MethodInfo methodToInject)
{
unsafe
{
if (IntPtr.Size == 4)
{
int* inj = (int*)methodToInject.MethodHandle.Value.ToPointer() + 2;
int* tar = (int*)methodToReplace.MethodHandle.Value.ToPointer() + 2;
*tar = *inj;
}
else
{
ulong* inj = (ulong*)methodToInject.MethodHandle.Value.ToPointer() + 1;
ulong* tar = (ulong*)methodToReplace.MethodHandle.Value.ToPointer() + 1;
*tar = *inj;
}
}
}
在原始程序尝试调用更改的方法之前,它工作正常。当它这样做时,整个程序停止,我得到一个access volation。我该如何解决这个问题?
【问题讨论】:
-
我认为您的应用程序中有一个插件架构,并且正在尝试使用包装器逻辑来跟踪插件中的方法调用?您是否尝试过依赖注入框架,例如托管可扩展性框架或 Microsoft Unity?这些提供了在动态加载的程序集周围实现包装器以执行此类操作的方法。
-
哪个版本的框架?
-
试试吧,不要打电话给
RuntimeHelpers.PrepareMethod()。 -
@Mr Anderson 哦,对不起,它的 .NET 3.5。
-
这个功能直到4.0才起作用。查看这个站点,特别是 cmets 线程,他们在其中讨论类型的内存映射在 3.5 和 4.0 之间是如何变化的。如果你更新你的框架,不管有没有
RuntimeHelpers.PrepareMethod(),它都可以工作。如果无法升级框架,请参考原始示例。 codeproject.com/Articles/37549/…
标签: c# pointers code-injection access-violation jit