Host guide
License Rhino and Grasshopper plugins
Build for Rhino's selected runtime, install the complete plugin output, then keep one Drawspan handle for the plugin lifetime.
Build for Rhino's selected runtime
On Windows, Rhino 8 can run plugins on .NET Framework 4.8 or modern .NET. Target net48 and net8.0-windows when supporting both modes. McNeel recommends this multi-targeting combination for Rhino 8 compatibility.
Install Drawspan.Client.V1 from NuGet into your plugin project. Use Rhino's SetDotNetRuntime command to see or change the selected mode, then restart Rhino as the command directs. Install the output matching that mode.
Copy package dependencies into the build output
A PackageReference supplies assemblies to the compiler; it does not define the final plugin installation. Modern .NET class libraries also leave package runtime assets out of dotnet build output by default. Set CopyLocalLockFileAssemblies in the Grasshopper project:
<PropertyGroup>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>This puts Drawspan.Client.V1.dll beside the built .gha. Keep RhinoCommon, Grasshopper and GH_IO non-copy-local because Rhino supplies them. McNeel likewise recommends excluding its host assemblies from plugin output.
Install the whole output folder
Copying only AcmeTools.Grasshopper.gha drops Drawspan.Client.V1.dll. Grasshopper may find the .gha, but .NET cannot resolve its Drawspan dependency, so the component does not load. Copy the complete output for the selected runtime into one plugin folder.
Use one of these layouts for your installation. The .pdb files help diagnostics but are not required to load the plugin.
%APPDATA%\Grasshopper\Libraries\AcmeTools\
# Rhino 8 in .NET Framework mode
AcmeTools.Grasshopper.gha
Drawspan.Client.V1.dll
AcmeTools.Grasshopper.pdb # optional
# Rhino 8 in .NET Core mode
AcmeTools.Grasshopper.gha
AcmeTools.Grasshopper.deps.json
Drawspan.Client.V1.dll
AcmeTools.Grasshopper.pdb # optionalUse your own plugin name for the folder and file prefix; keep the same file set.
Do not combine both runtime outputs in that folder. Build your plugin for the selected framework, then copy that output's plugin assembly and dependencies together.
Close the host and remove stale copies
Close Rhino before replacing the plugin folder. If Grasshopper is running inside another host, close that host too. A loaded .gha or dependency can remain locked for the life of the process; reinstalling over it then fails with an access-denied error.
A second .gha in another Grasshopper library folder can load beside the new copy. Duplicate components, duplicate component GUID messages, or changes that never appear usually mean an old copy is still being discovered. In Grasshopper, open File → Preferences → Solver → Plug-in loading → Valid Folders; McNeel documents that this list shows every folder Grasshopper searches for .gha files.
Close Rhino, then search each listed folder by exact plugin filename:
$folder = "$env:APPDATA\Grasshopper\Libraries"
Get-ChildItem -LiteralPath $folder -Filter 'AcmeTools.Grasshopper.gha' -File -Recurse |
Select-Object FullNameRepeat for any additional valid folder. Remove only folders belonging to old Acme Tools installations, including a legacy loose .gha directly under Libraries, then copy one complete runtime-specific folder back.
Own one handle for the plugin
In Grasshopper, use one lazy handle for the whole .gha. Do not start licensing on every component solve.
Gate the protected component solve
Read the current Status when a component is about to perform protected work. Licensed and Warning allow the solve; Unlicensed does not.
Continue with the integration examples
Client lifecycle example · Protect a component solve · Vendor configuration