
.net Lib.Harmony框架学习笔记
Lib.Harmony框架介绍
Lib.Harmony 是一个用于 .NET 应用程序的库,主要用于运行时的代码修改和补丁操作。它允许开发者在不修改源代码的情况下,对已编译的 .NET 程序进行动态补丁,通过方法拦截和插入自定义代码来改变程序行为。
Harmony 支持多平台运行,包括 Windows、Linux 和 macOS,灵活性高,可以通过 IL 代码精确控制程序行为。
它在游戏开发中的 Mod 开发和企业软件的热修复及功能扩展中得到广泛应用,并拥有活跃的社区支持。
官网地址:https://www.patreon.com/pardeike
安装Lib.Harmony包
这里创建了一个控制台项目,然后进行安装Lib.Harmony
。
基本使用
类拦截
简单来讲对类中的某个方法进行拦截处理返回的请求。
以下面的例子为例:
public class Worker
{
public string HandlerThings()
{
Console.WriteLine("调用了");
return "你好";
}
}
// 标记补丁目标类为 Worker
[HarmonyPatch(typeof(Worker))]
// 标记补丁目标方法为 Worker 类的 HandlerThings 方法
[HarmonyPatch(nameof(Worker.HandlerThings))]
public class HookWorker
{
/// <summary>
/// 前置补丁方法,会在 HandlerThings 方法执行前调用
/// </summary>
public static void Prefix()
{
Console.WriteLine("Prefix");
}
/// <summary>
/// 后置补丁方法,会在 HandlerThings 方法执行后调用
/// </summary>
public static void Postfix()
{
Console.WriteLine("Postfix");
}
/// <summary>
/// 最终补丁方法,会在 HandlerThings 方法执行完毕后调用
/// </summary>
public static void Finalizer()
{
Console.WriteLine("Finalizer");
}
}
using HarmonyLib;
using LearningLibHarmony;
using System.Reflection;
Worker worker = new Worker();
Console.WriteLine(worker.HandlerThings());
// 传任意参数
var harmony = new Harmony("hmy");
harmony.PatchAll(Assembly.GetExecutingAssembly());
Console.WriteLine();
Console.WriteLine(worker.HandlerThings());
我们可以把Prefix
改成bool,返回false将不会有任何返回值。
Prefix方法默认返回的true,表示需要调用原生方法,这里会将篡改的参数传入原生方法。
public static bool Prefix()
{
Console.WriteLine("Prefix");
return false;
}
using HarmonyLib;
using LearningLibHarmony;
using System.Reflection;
Worker worker = new Worker();
Console.WriteLine(worker.HandlerThings());
// 传任意参数
var harmony = new Harmony("hmy");
harmony.PatchAll(Assembly.GetExecutingAssembly());
Console.WriteLine();
Console.WriteLine("《?》"+worker.HandlerThings());
参数篡改
更改传入的参数。
public class Worker
{
public string HandlerThings(string instring1,string instring2)
{
Console.WriteLine($"调用了 参数1:{instring1} 参数2:{instring2}");
return instring1+ instring2;
}
}
// 标记补丁目标类为 Worker
[HarmonyPatch(typeof(Worker))]
// 标记补丁目标方法为 Worker 类的 HandlerThings 方法
[HarmonyPatch(nameof(Worker.HandlerThings))]
public class HookWorker
{
/// <summary>
/// 前置补丁方法,会在 HandlerThings 方法执行前调用
/// </summary>
public static bool Prefix(ref string instring1,ref string instring2)
{
Console.WriteLine($"Prefix Get param:{instring1} {instring2} ");
instring1 = "Prefix1";
instring2 = "Prefix2";
Console.WriteLine($"Update ====> {instring1} {instring2} ");
return true;
}
/// <summary>
/// 后置补丁方法,会在 HandlerThings 方法执行后调用
/// </summary>
public static void Postfix()
{
Console.WriteLine("Postfix");
}
/// <summary>
/// 最终补丁方法,会在 HandlerThings 方法执行完毕后调用
/// </summary>
public static void Finalizer()
{
Console.WriteLine("Finalizer");
}
}
using HarmonyLib;
using LearningLibHarmony;
using System.Reflection;
Worker worker = new Worker();
string mm = "mm";
string ff = "ff";
Console.WriteLine(worker.HandlerThings(mm,ff));
// 传任意参数
var harmony = new Harmony("hmy");
harmony.PatchAll(Assembly.GetExecutingAssembly());
Console.WriteLine();
Console.WriteLine("《?》"+worker.HandlerThings(mm,ff));
WPF自定义拦截
自定义消息框
public class Hmy_MessageBox
{
public void Hmy_Show(string messageBoxText)
{
MessageBox.Show(messageBoxText);
}
}
App中注册自动拦截
public partial class App : Application
{
//自动拦截注册
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var harmony = new Harmony("hmy");
harmony.PatchAll(Assembly.GetExecutingAssembly());
}
}
自动拦截类
[HarmonyPatch(typeof(Hmy_MessageBox))]
[HarmonyPatch(nameof(Hmy_MessageBox.Hmy_Show))]
[HarmonyPatch(new[] { typeof(string) })]
public class HookHmy_MessageBox
{
public static bool Prefix(ref string messageBoxText)
{
if (!(messageBoxText == "不会更改的弹窗"))
{
messageBoxText = "改了";
}
return true;
}
}
在窗体MainWindow.xaml里添加两个弹出提示框的按钮:
<Window x:Class="LearningLibHarmony.WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:LearningLibHarmony.WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Button Content="不会更改的弹窗" Width="120" Height="30" Click="Button_Click"></Button>
<Button Content="何明洋" HorizontalAlignment="Left" Click="Button_Click" Margin="264,336,0,0" VerticalAlignment="Top" Height="39" Width="196"/>
</Grid>
</Window>
public partial class MainWindow : Window
{
public Hmy_MessageBox _Hmy_MessageBox { get; set; }
public MainWindow()
{
InitializeComponent();
_Hmy_MessageBox = new Hmy_MessageBox();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var nowbutton = (Button)sender;
_Hmy_MessageBox.Hmy_Show(nowbutton.Content.ToString());
}
}
欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739
评价
排名
2
文章
634
粉丝
44
评论
93
docker中Sware集群与service
尘叶心繁 : 想学呀!我教你呀
一个bug让程序员走上法庭 索赔金额达400亿日元
叼着奶瓶逛酒吧 : 所以说做程序员也要懂点法律知识
.net core 塑形资源
剑轩 : 收藏收藏
映射AutoMapper
剑轩 :
好是好,这个对效率影响大不大哇,效率高不高
一个bug让程序员走上法庭 索赔金额达400亿日元
剑轩 : 有点可怕
ASP.NET Core 服务注册生命周期
剑轩 :
http://www.tnblog.net/aojiancc2/article/details/167
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2025TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:
50010702506256


欢迎加群交流技术