Add instance-specific method hooking support
Hooking was limited to capturing ALL method invocations across ALL instances. This adds support for hooking methods on specific instances only.
Architecture
Backend (ScubaDiver)
HookingCenter: Centralized registry mapping method+position → instance-specific callbacks usingConcurrentDictionary<int, HookRegistration>for O(1) operationsDiverBase: Per-method locks prevent race conditions during Harmony hook installation; unified callback dispatches to registered instancesResolveInstanceAddress: DotNetDiver uses pinned addresses orRuntimeHelpers.GetHashCode; MsvcDiver uses NativeObject addressesFunctionHookRequest: Added optionalInstanceAddressfield (0 = all instances, backward compatible)
Frontend (RemoteNET)
DiverCommunicator.HookMethod: Added optionalinstanceAddressparameterRemoteHookingManager: AcceptsRemoteObjector dynamic instances, prevents duplicate hooks per instance+positionRemoteObject: AddedHook()andPatch()convenience methods on both ManagedRemoteObject and UnmanagedRemoteObject
Usage
// Hook specific instance
var instance = app.GetRemoteObject(candidate);
instance.Hook(method, HarmonyPatchPosition.Prefix,
(ctx, inst, args, ref ret) => Console.WriteLine("Specific instance called"));
// Hook all instances (existing behavior unchanged)
app.HookingManager.HookMethod(method, HarmonyPatchPosition.Prefix, callback);
Notes
- Thread-safe: Per-method locks + concurrent collections
- Performance: O(1) hook registration/unregistration
- Limitation: Unpinned .NET objects use identity hashcode (collision possible)
- All ScubaDiver project files updated to include HookingCenter.cs
Original prompt
Hooking in the Scuba Diver ("back" end) and RemoteNET ("front" end) is currently limited to capturing ALL hits on the method. Some methods are STATIC/instance-less and it's FINE like this. But it's becoming common to want to hook a CLASS METHOD on a SPECIFIC INSTANCE.
Please modify the ScubaDivers (both .NET/MSVC) to allow another parameter called "instance" then implement hooking JUST for this instance.
We'd need a new centralized "Hooking Center" class that'll take care of registering for the hooks and then, using a callback of their own, re-route JUST the hits for any instances that were "registered".
In the RemoteNET side, change the API so such that we cann call Hook Method with this new optional argument - it should be a a RemoteObject or a DynamicRemoteObject Also add a "Hook" function to the RemoteObject class for easier access (it should mimic the API for hooking currently found on the RemoteApp class, but the INSTANCE is implied in this case, obviously)
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.