Search code examples
unity-game-enginedebuggingmono

How do I obtain static property value through mono debug wire?


I am trying to control Unity Editor over Mono Debugger Wire Protocol. I want to obtain value of public static property. The following is my attempt:

using VirtualMachine = Mono.Debugger.Soft.VirtualMachine;

// vm points to the virtual machine of the Unity Editor
internal void SomeWhat(VirtualMachine vm) {
    var hierarchyWindow = vm.GetTypes("UnityEditor.SceneHierarchyWindow", false)!.Single()!;
    var prev = hierarchyWindow.GetMethod("SelectPrevious")!;
    var latestWindow = hierarchyWindow
        .GetProperty("lastInteractedHierarchyWindow")
        .GetGetMethod(false)
        .Evaluate(null, new Value[] { });
    
    prev.Evaluate(latestWindow, new Value[] {});
}

However, it throws System.NotSupportedException:

Unhandled exception. System.NotSupportedException: Specified method is not supported.
   at Mono.Debugger.Soft.ILInterpreter.Evaluate(Value this_val, Value[] args) in $PROJECT/deps/debugger-libs/Mono.Debugger.Soft/Mono.Debugger.Soft/ILInterpreter.cs:line 43
   at Mono.Debugger.Soft.MethodMirror.Evaluate(Value this_val, Value[] args) in $PROJECT/deps/debugger-libs/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodMirror.cs:line 466
   at Blah.SomeWhat(VirtualMachine vm) in $PROJECT/$PROJECT_NAME/SandBox/Lib.cs:line $LINE

where $PROJECT, $PROJECT_NAME, and $LINE are variable.

I am confused because of its poor message, and a static field in Java's reflection do not require valid this_val object. It turns out that this_val cannot be null at present.

I am using Unity Editor 2019.4.31f1 and mono/debugger-libs on https://github.com/mono/debugger-libs/tree/6fcc6d78446b1fffac12f597099cc3d78dd74ca6, any ideas?


Solution

  • line 42 in ILInterpreter does check for

    if (method.IsStatic || ... || this_val == null || ...) 
       throw new NotSupportedException ();
    

    so it looks like this - or at least this way - is not made for statics at all.


    Since in this specific case the property is actually just pointing to a static field

    private static SceneHierarchyWindow s_LastInteractedHierarchy;

    you could try to rather go through e.g.

    var fieldInfoMirror = hierarchyWindow.GetField("s_LastInteractedHierarchy");
    var latestWindow = hierarchyWindow.GetValue(fieldInfoMirror);
    

    Alternatively you could probably also try and go through

    var property = hierarchyWindow.GetProperty("lastInteractedHierarchyWindow");
    var getterMethod = property.GetGetMethod();
    var latestWindow = hierarchyWindow.InvokeMethod(null, getterMethod, new Value[0]);
    

    It depends a lot on your actual use case and purpose of what you are trying to implement.

    Usually in a case like yours where you already know exactly what type and members and signatures you are dealing with you would rather use InvokeMethod instead of Evaluate. The latter as to my understanding you would use more if you do not know the types, members and signatures beforehand.