c#变更方式';s指针.NET3.5

c#变更方式';s指针.NET3.5,c#,pointers,code-injection,access-violation,jit,C#,Pointers,Code Injection,Access Violation,Jit,我试图在运行时替换插件加载程序(如)中的一个方法。我无法在此实例中直接修改程序集文件。整个目的是能够知道何时调用这些方法。必要时取消。加载插件后,我将运行以下代码: public static void PluginLoaded() { replace(); } public static void replace() { MethodInfo oldMethod, newMethod; oldMethod = typeof(<other assem

我试图在运行时替换插件加载程序(如)中的一个方法。我无法在此实例中直接修改程序集文件。整个目的是能够知道何时调用这些方法。必要时取消。加载插件后,我将运行以下代码:

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;
        }
    }
}
publicstaticvoidpluginload()
{
替换();
}       
公共静态void replace()
{
方法信息旧方法,新方法;
oldMethod=typeof().GetMethod(“”,BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic,null,新类型[]{typeof(ushort)},null);
newMethod=typeof(NewEvents).GetMethod(“,BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic,null,新类型[]{typeof(ushort)},null);
RuntimeHelpers.PrepareMethod(oldMethod.MethodHandle);
RuntimeHelpers.PrepareMethod(newMethod.MethodHandle);
替换内部(旧方法、新方法);
}
静态void ReplaceInner(MethodInfo methodToReplace、MethodInfo methodToInject)
{
不安全的
{
如果(IntPtr.Size==4)
{
int*inj=(int*)methodToInject.MethodHandle.Value.ToPointer()+2;
int*tar=(int*)methodToReplace.MethodHandle.Value.ToPointer()+2;
*焦油=*inj;
}
其他的
{
ulong*inj=(ulong*)methodToInject.MethodHandle.Value.ToPointer()+1;
ulong*tar=(ulong*)methodToReplace.MethodHandle.Value.ToPointer()+1;
*焦油=*inj;
}
}
}

它工作正常,直到原始程序尝试调用更改的方法。当它这样做时,整个程序停止,我得到一个。如何修复此问题?

您提供的功能特定于从.Net 4.0版开始的CLR的内存映射。以下是您的选择:

备选案文1。升级计算机上的.NET Framework。这将解决您的问题,而无需升级visual studio

备选案文2。更新
ReplaceInner()
方法以反映.NET framework 4.0之前的类型和方法的内存映射:

static void ReplaceInner(MethodInfo methodToReplace, MethodInfo methodToInject)
{
    unsafe
    {
        if (IntPtr.Size == 4)
        {
            uint* tarPtr = (uint*)methodToReplace.MethodHandle.Value.ToPointer();
            uint* injPtr = (uint*)methodToInject.MethodHandle.Value.ToPointer();

            uint* tar = (uint*)*(tarPtr + 5) + 12;
            uint* inj = (uint*)*(injPtr + 5) + 12;
            *tar = *inj;
        }
        else
        {
            ulong* tarPtr = (ulong*)methodToReplace.MethodHandle.Value.ToPointer();
            ulong* injPtr = (ulong*)methodToInject.MethodHandle.Value.ToPointer();

            ulong* tar = (ulong*)*(tarPtr + 5) + 12;
            ulong* inj = (ulong*)*(injPtr + 5) + 12;
            *tar = *inj;
        }
    }
}

我认为您的应用程序中有一个插件体系结构,并且正在尝试使用包装器逻辑来跟踪插件中的方法调用?您是否尝试过依赖注入框架,如托管可扩展性框架或Microsoft Unity?这些方法提供了围绕动态加载的程序集实现包装器的方法,以执行类似的操作。哪个版本的框架?请不要调用
RuntimeHelpers.PrepareMethod()
@Mr Anderson Oh抱歉,它的.NET 3.5。此函数在4.0之前不起作用。看看这个网站,特别是评论线程,他们在这里讨论一种类型的内存映射在3.5和4.0之间是如何变化的。如果您更新您的框架,无论是否使用
RuntimeHelpers.PrepareMethod()
,都可以使用。如果无法升级框架,请参考原始示例@michaelbecker我稍微修改了代码。试试这个。@michaelbecker这个异常是什么时候发生的?运行
ReplaceInner()
或调用新的注入方法时?调用ReplaceInner()时。使用Try{}Catch{}我发现是这段代码在做“*tar=*inj;”(对于第二段代码,作为x64上的im)@michaelbecker我目前无法访问64位环境来调试它-我会在可能的时候提供帮助。在x64中为
*tar=*inj
抛出NullReferenceException。有人知道如何让它在x64模式下工作吗?