C#-使用Harmony库实现DLL文件反射调用

一. Harmony工作原理

     利用C#运行时Runtime的反射机制,动态加载dll中的方法,字段,属性,实现对DLL方法的重写和代码注入。

二. Harmony下载及安装

     1.下载Harmony_lib库lib.harmony.2.3.3.nupkg

霸王•吕布 / CSharpHarmonyLib · GitCodeicon-default.png?t=N7T8https://gitcode.net/qq_35829452/csharpharmonylib     2.csproj添加reference引用

<Reference Include="0Harmony">
    <HintPath>..\..\Tool\C#\lib.harmony.2.3.3\lib\net48\0Harmony.dll</HintPath>
</Reference>

     3.通过创建Harmony实例,调用PatchAll()方法实现补丁类的加载

#加载已经实现的补丁类,重写原有DLL中方法
var harmonyPatch = new Harmony("patch");
harmonyPatch.PatchAll();

三. Harmony前置插桩,后置插桩

     通过在类实例上添加Harmony注解,实现补丁类,添加Prefix,Postfix实现对调用方法前,调用方法后的重写,返回值true/false决定原DLL方法是否被执行。

[HarmonyPatch(typeof(OriginalClass), "OriginalMethod")]
public class MyHarmonyPatch
{
    __instance获取类实例,___a获取实例变量
    public static bool Prefix(int ___a, string ___c, OriginalClass __instance)
    {
        // 在这里编写补丁的逻辑
        Console.WriteLine("Patched method called!");
        Console.WriteLine(___c);
        return true; // 返回false将阻止原方法执行
    }

    public static bool Postfix(string ___c)
    {
        // 在这里编写补丁的逻辑
        Console.WriteLine("Patched method called!");
        Console.WriteLine(___c);
        return true; // 返回false将阻止原方法执行
    }
}

public class OriginalClass
{
    int a = 10;

    int b = 20;

    string c = "abc";
    public void OriginalMethod()
    {
       Console.WriteLine("Original method called!");
    }

    public void OtherMethod()
    {
       Console.WriteLine("Other Method called!");
    }
}

四. Traverse访问私有属性&私有方法

#访问私有属性
OriginalClass originalClass = new OriginalClass();
string value = Traverse.Create(originalClass).Field("a").GetValue<int>() + "a";
Console.WriteLine(value);

#访问私有方法Method("12")
OriginalClass originalClass = new OriginalClass();
bool methodExisits = Traverse.Create(originalClass).Method("12").MethodExists();
Console.WriteLine(methodExisits);

     

五. AccessTool

     使用AccessTool对类进行反射,动态调用目标类的方法。

#AccessTool反射调用目标dll方法
MethodInfo method = AccessTools.Method(typeof(OriginalClass), "OtherMethod");
method.Invoke(__instance, new object[0]);


#AccessTool反射调用目标dll属性字段
FieldInfo info = AccessTools.Field(typeof(OriginalClass), "b");
Console.WriteLine(info.GetValue(__instance));

相关推荐

  1. 使用python调用dll

    2024-04-21 06:14:03       23 阅读
  2. c# 如何调用指定文件夹里面的动态dll

    2024-04-21 06:14:03       32 阅读
  3. 首次实现Go调用Cdll文件

    2024-04-21 06:14:03       43 阅读
  4. c#程序调用c++开发dll

    2024-04-21 06:14:03       30 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-21 06:14:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-21 06:14:03       101 阅读
  3. 在Django里面运行非项目文件

    2024-04-21 06:14:03       82 阅读
  4. Python语言-面向对象

    2024-04-21 06:14:03       91 阅读

热门阅读

  1. appium控制手机一直从下往上滑动

    2024-04-21 06:14:03       31 阅读
  2. c++自制小游戏:c++人生重开模拟器(修仙版)

    2024-04-21 06:14:03       37 阅读
  3. mysql like 查询包含%

    2024-04-21 06:14:03       39 阅读
  4. PostgreSQL 窗口函数汇总

    2024-04-21 06:14:03       33 阅读
  5. 个人练习之-jenkins

    2024-04-21 06:14:03       31 阅读