Moving plugin to Rhino 8

I’m working to get my plugin working in Rhino 8. I at first tried to switch to the .net 7 framework, but ran into a bunch of problems. So I’m sticking with 4.8. I think I saw this suggested somewhere anyways and it seems to be working fine now. Please someone let me know if I should really be getting it to work with .net 7. For instance, will 4.8 eventually stop working in Rhino for the current or upcoming versions?

The one issue I am having is that I can’t launch rhino anymore from visual studios. I get the below error. Any suggestion how to fix this?

Thanks,
Sam

a fatal error has occurred and debugging needs to be terminated. the debugger was configured to use the desktop clr (.net framework) managed debugger, but the target process loaded the coreclr (.net core) runtime. To debug this project, configure it to use the ‘Managed (CoreCLR)’ debugger.

1 Like

The official way (suggested by Microsoft) to create a library that is compatible with both .net framework 4.8 and .net 7 is to set the <TargetFramework> to netstandard2.0. This will produce a single dll (or .rhp, .gha) that is guaranteed to be compatible with both.

The only downside I found is that there are in practice a few (but very few) apis that exist in both net48 and net7 but not in netstandard2.0 for some reason. But at least the opposite is not the case: there are no apis in net standard 2.0 that don’t exist in net48 or net7.

You can also multi-target to both, but that will produce two separate dlls. You could use mult-targeting just to get Visual Studio to tell you which apis are compatible with both, which would then not error on the very few missing ones, and then just use the net48 version on both Rhino 7 and 8 (this is probably what McNeel would suggest).

This is probably also fine if you’re just creating an .rhp, but if at some point you plan to create Nuget packages I recommend using net standard.

EDIT: Should probably also mention that net standard does not include Windows specific apis, for example, to access the Windows registry, WPF, etc. Which exist in both net48 and net7.0-windows.
(The missing apis I was referring above are not these, but ones that exist in net7.0 without the -windows).

1 Like

Thanks vicente. This stuff is quite over my head… I’m going to have to do some learning… but for now it does sound reasonable to just ust .net 4.8.

Did you see my question about the fatal error? It says to configure the project to use the ‘Managed (CoreCLR)’ debugger, but I have no clue how to do that and not getting much luck with solutions from googling it… You or anyone else out there able to guide me through this please?

I’ve never got that error, but from the text it might be related to trying to debug a library targeting net framework 4.8, in Rhino 8 using the new .net 7.0. You might have to change the debugger configuration to force it to use CoreCLR.

I don’t know if this is the issue, but if it is, it’s another reason to just target netstandard2.0 as recommended.

The debugging may be trying to use 7.0 and failing.

I’m generally writing plugins which work under 4.8 or 7.0 and have not seen this problem.

I’ll throw the following out anyway.

Two suggestions:

  1. This looks like a debugger problem. Have you tried the release build within both Rhino 7.0 and 8.0? If it works in 7.0 then you know you’re supporting 4.8 correctly. Does that work better than the debug build? (including adding a few MessageBox(“”) popups at key stages like plugin load if necessary to track progress. I’m not saying this would solve the problem, but if the release build works then it tells you that the problem is exclusively the debugger configuration.
  2. for the debug build, try using the command line option to force Rhino to use 4.8.

Hey @samlochner,

If you want to support Rhino 7 (win and/or mac), you’ll need to release net48 until you sunset that support. Also to keep in mind. Rhino 8 will likely run net48 for its lifetime as Rhino 8 still runs net48, and Rhino.Inside.Revit is quite popular and has to use the same framework.

In theory, for now, supporting just net48 is easier (if you don’t want to do Mac). You can of course start multi-targeting now so you’re prepared for the switch to dotnet and or cross-platform.

You’ll need to use <TargetFrameworks>net48;net7.0</TargetFrameworks> inside your .csproj for this.

If you want to have a debug setup for net48 and net7.0 you’ll need to update your launch settings to force Rhino to launch in dotnet7.0 mode. I use the following launchsettings.json you need to add this to your build.

	"profiles": {
		"Win Rhino 7 net48": {
			"commandName": "Executable",
			"executablePath": "C:\\Program Files\\Rhino 7\\System\\Rhino.exe",
			"commandLineArgs": "/nosplash"
		},
		"Win Rhino 8 net48": {
			"commandName": "Executable",
			"executablePath": "C:\\Program Files\\Rhino 8\\System\\Rhino.exe",
			"commandLineArgs": "/nosplash /netfx"
		},
		"Win Rhino 8 Net7.0": {
			"commandName": "Executable",
			"executablePath": "C:\\Program Files\\Rhino 8\\System\\Rhino.exe",
			"commandLineArgs": "/nosplash /dotnet"
		},

You can fix your issue by opening Rhino 8 outside of Visual Studio and running the setDotNetRuntime command.

– cs

P.S - You are on windows, correct?

7 Likes

CSykes, I’m on windows. Running setDotNetRuntime and setting runtime to netframework solved the problem, thanks! I think it’s only me that has to do this to get VS to be able to launch and debug and my users can just stick with default runtime when using the plugin. Though I have noticed a couple bugs in my plugin when running in default runtime and I’m going to have to dig into them…

Thank you everyone for your support. For now I’m going to keep going with 4.8. It sounds like it will always work in Rhino 8, so that should buy me a few years…

1 Like

Just as a note, the setdotnetruntime approach changes the default startup to 4.8.

If you want to be able to flip back and forth to test both ways (to confirm that it works under 7.0 moving forward) you can use the corresponding command line options.

Rhino - Moving to .NET 7 (rhino3d.com)

1 Like

@csykes, @Nathan_Bossett do you know of any downsides of targeting just netstandard2.0? (if you’re not using Windows APIs)

I started targeting 4.8 and 7.0 because that’s what the McNeel sample code and project creators for Visual Studio do.

My assumption is that:

  1. this guarantees that any framework tools Visual Studio will let me invoke will be present if Rhino is.
  2. Being more specific may let Visual Studio give me more warnings (or, conversely, know that what I’m doing is safe in the context I’m doing it).
  3. being maximally specific assures that the environment I’m testing in matches the environment the user is trying to run it in.
  4. I have less risk of weird compiler or deployment problems if I follow a “Monkey see, monkey do” approach and follow McNeel.

I don’t know the extent to which those assumptions may be effectively enforced by the compiler. I could also be completely wrong: I haven’t done much wide deployment of .net tools across different runtimes yet.

All of those issues is what net standard is supposed to address.

I have less risk of weird compiler or deployment problems if I follow a “Monkey see, monkey do” approach and follow McNeel.

I think this mentality is right, but in this case I would follow what Microsoft recommends, which are the ones that created the different runtimes and developer tools.

I don’t think there’s anything wrong with the multi-targeting approach, I just find it strangely unusual that if you search for net standard in this forum there’s almost no results, but is what is supposed to be the proper solution, so I thought there might be something else to it.

An excellent question @visose!

RhinoCommon targets net4.8 so you can’t target any lower than that, ipso facto, you can’t target netstandard2.0 when using RhinoCommon.

If you’re writing a library that doesn’t reference it then I personally multi-target to netstandard2.0 and (net6.0 or net7.0).

Netstandard is fine and dandy, but the new NetCore releases really do have some incredible speed improvements put into them, and I like to take advantage of those where I can.

– cs

This is not correct, you might be under the impression that .net standard is an older runtime. I recommend you read this article: .NET Standard - .NET | Microsoft Learn. You can see it recommends targeting net standard 2.0 for libraries that should work with .net framework 4.8 and .net 7.0.

Netstandard is fine and dandy, but the new NetCore releases really do have some incredible speed improvements put into them, and I like to take advantage of those where I can.

This is also not correct. If you target .net standard for compilation, at runtime it will still use .net 7 and all of the performance improvements.

I’m almost 100% sure you can’t create a netstandard2.0 project and consume the RhinoCommon Nuget.

I did not know that 2nd part. Really handy to know! I figured the compiler might have some newer tricks too, but I guess it’s going to use the latest compiler regardless.

You can consume RhinoCommon, you will get the same warning as when targeting .net 7 since RhinoCommon targets only net48. The problem as I said above is if you need to use Windows only APIs. For example, you might need to create icons that require the Bitmap class under System.Drawing.

1 Like

What a day of learning I am having :slight_smile: .

Hey Everyone,

While .NET Standard 2.0 (not 2.1) would work for both .NET 4.8 and .NET 7 runtimes, we have some upcoming features in Rhino 8.2 that will help here. We are going to support multi-targeting of plugins so that you can create a net48 version of your plugin to support Rhino 7 (and 8 when running in .NET 4.8), and also the ability to have a .NET 7 specific version to take advantage of newer functionality and even platform specific APIs.

See RH-76604 for information (and a sample project) that targets all the different supported runtimes and platforms.

Cheers,
Curtis.

3 Likes

One thing I forgot to mention, is you can actually use the System.Drawing.Common nuget package when you need System.Drawing apis (just don’t include it with your plugin). On Mac, we have our own version of System.Drawing that will be loaded instead that we have been using/improving since Rhino 5, which is how GH works on Mac.

Alternatively, Eto.Forms has a lot of the same APIs so if you are writing new code it would be recommended to use that instead.

1 Like

@curtisw I noticed in Rhinocommon 8+ there are some new overloads to avoid using anything under System.Drawing, for example to create a panel you can pass a resource string for an icon, rather than a System.Drawing.Icon.

Not sure if it’s possible to backport these to Rhino 7 on a future service release (understanding that users will require the latest SR for Rhino 7).

Hey @visose,

Sorry, it is very unlikely for that to be back ported as there was a lot of plumbing that went into Rhino 8 to support that and to avoid having to go “through” System.Drawing when all of the UI is now in Eto.Forms.

1 Like