public static void TestHooks() { Console.WriteLine("Hooks: none"); DetourExample.TestStep(5, 6, 8); Console.WriteLine(); IDetour hookTestMethodA = new Hook( typeof(DetourExample).GetMethod("TestMethod", BindingFlags.Instance | BindingFlags.Public), typeof(HookTest).GetMethod("TestMethod_A", BindingFlags.Static | BindingFlags.Public) ); IDetour hookTestStaticMethodA = new Hook( typeof(DetourExample).GetMethod("TestStaticMethod", BindingFlags.Static | BindingFlags.Public), typeof(HookTest).GetMethod("TestStaticMethod_A", BindingFlags.Static | BindingFlags.Public) ); IDetour hookTestVoidMethodA = new Hook( typeof(DetourExample).GetMethod("TestVoidMethod", BindingFlags.Static | BindingFlags.Public), typeof(HookTest).GetMethod("TestVoidMethod_A", BindingFlags.Static | BindingFlags.Public) ); Console.WriteLine("Hooks: A"); DetourExample.TestStep(42, 12, 1); Console.WriteLine(); IDetour hookTestMethodB = new Hook( typeof(DetourExample).GetMethod("TestMethod", BindingFlags.Instance | BindingFlags.Public), typeof(HookTest).GetMethod("TestMethod_B", BindingFlags.Static | BindingFlags.Public) ); IDetour hookTestStaticMethodB = new Hook( typeof(DetourExample).GetMethod("TestStaticMethod", BindingFlags.Static | BindingFlags.Public), new Func <Func <int, int, int>, int, int, int>((orig, a, b) => { return(orig(a, b) + 2); }) ); IDetour hookTestVoidMethodB = new Hook( typeof(DetourExample).GetMethod("TestVoidMethod", BindingFlags.Static | BindingFlags.Public), new Action <Action <int, int>, int, int>((orig, a, b) => { Console.WriteLine("Hook B"); DetourExample.VoidResult += 2; orig(a, b); }) ); Console.WriteLine("Hooks: A + B"); DetourExample.TestStep(42 + 42, 12 + 2, 3); Console.WriteLine(); hookTestMethodA.Undo(); hookTestStaticMethodA.Undo(); hookTestVoidMethodA.Undo(); Console.WriteLine("Hooks: B"); DetourExample.TestStep(5 + 42, 6 + 2, 12); Console.WriteLine(); hookTestMethodB.Undo(); hookTestStaticMethodB.Undo(); hookTestVoidMethodB.Undo(); Console.WriteLine("Detours: none"); DetourExample.TestStep(5, 6, 8); Console.WriteLine(); }
public static void TestStep(int instanceExpected, int staticExpected, int voidExpected) { DetourExample instance = new DetourExample(); int instanceResult = instance.TestMethod(2, 3); Console.WriteLine($"instance.TestMethod(2, 3): {instanceResult}"); Assert.AreEqual(instanceExpected, instanceResult); int staticResult = TestStaticMethod(2, 3); Console.WriteLine($"TestStaticMethod(2, 3): {staticResult}"); Assert.AreEqual(staticExpected, staticResult); Console.WriteLine("TestVoidMethod(2, 3):"); VoidResult = 0; TestVoidMethod(2, 3); Assert.AreEqual(voidExpected, VoidResult); }
public static int TestMethod_B(Func <DetourExample, int, int, int> orig, DetourExample self, int a, int b) { return(orig(self, a, b) + 42); }
public static int TestMethod_A(DetourExample self, int a, int b) { return(42); }
public static int TestMethod_B(DetourExample self, int a, int b) { return(120); }
public static void TestDetours() { Console.WriteLine("Detours: none"); DetourExample.TestStep(5, 6, 8); Console.WriteLine(); // Three examples of using Detour. // Note that if you need non-layered, low-level hooks, you can use NativeDetour instead. // This is also why the variable type is IDetour. // System.Linq.Expressions, thanks to leo (HookedMethod) for telling me about how to (ab)use MethodCallExpression! IDetour detourTestMethodA = new RuntimeDetour.Detour( () => default(DetourExample).TestMethod(default(int), default(int)), () => TestMethod_A(default(DetourExample), default(int), default(int)) ); // Method references as delegates. IDetour detourTestStaticMethodA = new Detour <Func <int, int, int> >( DetourExample.TestStaticMethod, TestStaticMethod_A ); // MethodBase, old syntax. IDetour detourTestVoidMethodA = new RuntimeDetour.Detour( typeof(DetourExample).GetMethod("TestVoidMethod", BindingFlags.Static | BindingFlags.Public), typeof(DetourTest).GetMethod("TestVoidMethod_A", BindingFlags.Static | BindingFlags.Public) ); Console.WriteLine("Detours: A"); DetourExample.TestStep(42, 12, 1); Console.WriteLine("Testing trampoline, should invoke orig, TestVoidMethod(2, 3)"); detourTestVoidMethodA.GenerateTrampoline <Action <int, int> >()(2, 3); Console.WriteLine(); IDetour detourTestMethodB = new RuntimeDetour.Detour( () => default(DetourExample).TestMethod(default(int), default(int)), () => TestMethod_B(default(DetourExample), default(int), default(int)) ); IDetour detourTestStaticMethodB = new RuntimeDetour.Detour( () => DetourExample.TestStaticMethod(default(int), default(int)), () => TestStaticMethod_B(default(int), default(int)) ); IDetour detourTestVoidMethodB = new RuntimeDetour.Detour( () => DetourExample.TestVoidMethod(default(int), default(int)), () => TestVoidMethod_B(default(int), default(int)) ); Console.WriteLine("Detours: A + B"); DetourExample.TestStep(120, 8, 2); Console.WriteLine("Testing trampoline, should invoke hook A, TestVoidMethod(2, 3)"); Action <int, int> trampolineTestVoidMethodB = detourTestVoidMethodB.GenerateTrampoline <Action <int, int> >(); trampolineTestVoidMethodB(2, 3); Console.WriteLine(); detourTestMethodA.Undo(); detourTestStaticMethodA.Undo(); detourTestVoidMethodA.Undo(); Console.WriteLine("Detours: B"); DetourExample.TestStep(120, 8, 2); Console.WriteLine("Testing trampoline, should invoke orig, TestVoidMethod(2, 3)"); trampolineTestVoidMethodB(2, 3); Console.WriteLine(); detourTestMethodB.Undo(); detourTestStaticMethodB.Undo(); detourTestVoidMethodB.Undo(); Console.WriteLine("Detours: none"); DetourExample.TestStep(5, 6, 8); Console.WriteLine(); }