如何在闭源且类密封、方法非虚的外部API中监听指定方法调用?
如何在闭源且类密封、方法非虚的外部API中监听指定方法调用?
这种情况我太懂了!碰到不维护的闭源API,还不给你需要的回调事件,确实让人头疼。不过不用走反编译改程序集的弯路,咱们有更优雅的运行时拦截方案——用方法钩子/IL注入技术,其中Harmony这个开源库特别适合你的场景,它能在不修改原程序集的前提下,给目标方法注入自定义逻辑。
核心思路
Harmony的原理是在运行时动态修改目标方法的IL代码,给它打上“补丁”——你可以选择在原方法执行前、执行后,甚至替换原方法逻辑。对你来说,只需要用postfix补丁,也就是在ApiClass.SomeMethod执行完成后,自动触发你的回调函数,完全不会影响原方法的参数、返回值或执行流程。
具体实现步骤
安装Harmony库
先通过NuGet安装Harmony的包,用.NET CLI的话就是:dotnet add package Lib.Harmony或者在Visual Studio的NuGet包管理器里搜索
Lib.Harmony安装。编写拦截逻辑
把你的MyClass改成下面这样,完全贴合你的需求:using HarmonyLib; public class MyClass { private Harmony _harmonyInstance; public void Init(ApiClass obj) { // 用唯一标识初始化Harmony,建议用你的插件ID,避免和其他插件冲突 _harmonyInstance = new Harmony("com.your.plugin.unique.identifier"); // 给ApiClass的SomeMethod打postfix补丁 _harmonyInstance.Patch( // 获取目标方法:用AccessTools工具类定位闭源类的方法 original: AccessTools.Method(typeof(ApiClass), nameof(ApiClass.SomeMethod)), // 指定我们的回调方法作为postfix,在原方法执行后触发 postfix: new HarmonyMethod(typeof(MyClass), nameof(MyCallback)) ); } // 注意:postfix方法的签名要和原方法匹配(如果原方法有参数/返回值,这里也要对应) // 这里原方法是无参无返回值,所以我们的回调也用无参 public static void MyCallback() { // 这里写你要执行的逻辑,每次SomeMethod被调用后都会触发 // 比如更新你的插件状态、同步数据等等 Console.WriteLine("ApiClass.SomeMethod 被调用了!"); } // 重要:插件卸载时一定要清理补丁,避免内存泄漏或影响其他功能 public void Cleanup() { _harmonyInstance?.UnpatchAll(); } }
关键细节说明
- AccessTools工具类:Harmony提供的这个类可以帮你轻松定位闭源类的方法、属性,不用直接引用原API的内部代码,完美适配闭源场景。
- Postfix补丁:专门用于在原方法执行后触发逻辑,完全符合你的需求——不干扰原方法的任何行为,只是“监听”它的调用事件。
- 补丁清理:一定要在插件卸载或者不再需要监听时调用
UnpatchAll(),否则可能会导致内存泄漏,或者和其他使用Harmony的插件产生冲突。
其他备选方案(不推荐,难度高)
如果不想用第三方库,你也可以用.NET Reflection.Emit手动生成IL代码来替换目标方法,但这个方式需要你对IL指令有深入了解,实现起来非常繁琐,而且容易出错,远不如Harmony省心。
注意事项
- 确保你的插件和目标API的.NET版本兼容(比如目标是.NET Framework 4.7,你的插件也要对应版本)。
- 如果原方法有参数或返回值,你的postfix方法需要对应签名,比如原方法是
public int SomeMethod(string arg),那么你的回调可以写成public static void MyCallback(string arg, int __result),其中__result是原方法的返回值,Harmony会自动注入这些参数。 - 少数工具可能有反篡改机制,但普通桌面应用一般不会限制这种运行时IL修改。
备注:内容来源于stack exchange,提问作者AlexM
相关产品推荐
相关产品推荐

