2016-08-29 14 views
-1

Я пытаюсь заменить метод в загрузчике плагинов (например, Bukkit for Minecraft) во время выполнения. Я не могу изменить файл сборки непосредственно в этом экземпляре. Вся цель состоит в том, чтобы иметь возможность сказать, когда вызываются методы. И отмените их, если необходимо. Как только мой плагин загружен, я запускаю следующий код:C# указатель метода изменения .NET 3.5

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. Как это исправить?

+0

я беру его у вас есть плагин архитектуры приложения и пытаются иметь логику обертки для вызовов метода отслеживания в плагине (-ах)? Пробовали ли вы систему подстановки зависимостей, такую ​​как Managed Extensibility Framework или Microsoft Unity? Они предоставляют способы реализации оберток вокруг динамически загружаемых сборок, чтобы делать такие вещи. – ajawad987

+0

Какая версия рамки? –

+0

Попробуйте, не называя 'RuntimeHelpers.PrepareMethod()'. –

ответ

2

Функциональность, которую вы предоставили, специфична для сопоставления памяти CLR, начиная с .Net версии 4.0. Вот ваши варианты:

Вариант 1. Обновите платформу .NET Framework на своем компьютере. Это должно исправить вашу проблему без необходимости обновления visual studio. https://www.microsoft.com/en-us/download/details.aspx?id=42643

Вариант 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; 
     } 
    } 
} 
+0

@michaelbecker Я немного изменил код. Попробуй это. –

+0

@michaelbecker, когда произошло это исключение? При запуске 'ReplaceInner()' или при вызове вашего нового метода ввода? –

+0

при вызове ReplaceInner(). Использование Try {} Catch {} Ive выяснил, что его этот код делает это «* tar = * inj;». (Для второго в im на x64) –