Home Fix Harmony.UnpatchAll
Post
Cancel

Fix Harmony.UnpatchAll

The problem

Have you ever noticed that Harmony.UnpatchAll method unpatches everything, even patches which made in other assemblies if you don’t pass harmonyID?

1
public void UnpatchAll(string harmonyID = null)

This could lead to a real headace and problems, let’s say you or someone’s else have a plugin and at some point its unloaded/disposed and do this:

1
2
3
4
5
/// Called when plugin is unloading or disposing
void UnloadPlugin()
{
    harmony.UnpatchAll(); // Don't do it, it unpatches everything
}

You see? It will just unpatch everything, other plugins and your.

Solution

Pass the ID of your Harmony instance

Instead, pass the Id of your harmony instance to unpatch only your own patches, but still it might not work, recommend looking next solution.

1
2
3
4
5
/// Called when plugin is unloading or disposing
void UnloadPlugin()
{
    harmony.UnpatchAll(harmony.Id);
}

Patch Harmony.UnpatchAll and force ID

Upper solution might not work because you might have a lot of plugins even not made by yourself, so in this case we will patch the Harmony.UnpatchAll to fix this problem everywhere.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/// <summary>
/// Caution for developers: Using `Harmony.UnpatchAll()` without specifying a Harmony ID will unpatch methods across all assemblies, not just your own, this is a solution for this problem.
/// </summary>
[HarmonyPatch]
internal static class PatchHarmony
{
    [HarmonyPrefix]
    [HarmonyPatch(typeof(Harmony), nameof(Harmony.UnpatchAll))]
    private static void Prefix(Harmony __instance, ref string harmonyID)
    {
        if (harmonyID == null) // or you can use instead `string.IsNullOrEmpty(harmonyId)` or `string.IsNullOrWhiteSpace(harmonyId)`
        {
            harmonyID = __instance.Id;
        }
    }
}
This post is licensed under CC BY 4.0 by the author.

No one pays me for the Unit Tests

AssemblyResolve And Mono