I’ve seen a lot of threads about debugging and having to restart Rhino between sessions. I’m curious if there’s any updated tips and tricks as we knock on 2020’s door.
Have the plugin act as a shim that dynamically loads assembly → Rebuild → Reattach to process?
Anything with Rhino Inside?
It works with two copies of VS open. The first has the shim project and is attached to Rhino. The second has the actual plugin. You can rebuild the actual plugin and the shim loads the fresh compile when the next command executes.
The shim could be 100% generated using a plugin’s signature to stub out the reflection calls. I’m not sure why VS is locking the obj\Debug\ files, but deleting them before loading the bin\Debug files works.
Basically you have a shim and a normal plugin. You want to load the shim and debug it. For the normal plugin, you want to disable it in Rhino through the _PluginManager (accidentally running the normal command will prevent you from rebuilding) and unload the project in VS (force it to use the debug symbols supplied through reflection).
I’ve just tested this for Visual Studio 2019, and the instructions are identical to my previous post. The .sln file provided by EricM is for VisualStudioVersion = 16.0.29613.14, which is 2019, so yeah, I was the one behind the times here.
Sorry, I don’t trust edit&continue type of technologies. I prefer to close Rhino, compile my work and restart Rhino.
As such I have not tried any of the solutions that have been surfaced on our forum.
I don’t know if any of the other Rhino devs, or plug-in devs have used this technique in GH (or in Rhino for that matter). @stevebaer@DavidRutten@curtisw@dale anyone?
To be fair, my shim isn’t edit and continue. It’s a full recompile to change something. You just don’t have to restart Rhino because the shim loads the freshly recompiled assembly.
I am using the latest github repo. And did the following:
samplePlugin pdb and rhp are copied to original _shimCopy and _rhinoCopy.
InShimCmd1.cs, the four fields were updated. But I am a little confused, because currently I put class name in the commandName field. Besides, my namespace has a dot.
The rest remained unchanged. Would be great if you can point me to the right direction in tackling this.
In the target command, do you have a SetShimInstance method?
public class MirrorXYZ : Command
{
public static Command Instance { get; private set; }
public MirrorXYZ()
{
Instance = this;
}
private void SetShimInstance(Command shim)
{
Instance = shim;
}
I’m trying to remember how that bit of plumbing works. When there’s History, Rhino uses Command.Instance to log the proper plugin command to the HistoryTable. But that doesn’t work with a plugin assembly loaded via reflection. I think I used SetShimInstance to overwrite the default Instance definition (this) with the shim’s. Then when Rhino calls ReplayHistory() on the shim, the shim reloads your target assembly and executes the command there.
In the end I commented out the part that works on history replay (the last 5 lines). I guess it is because I have not implemented a method for history replay. After that everything works great.