Embedding and Loading a DLL in a Grasshopper Plugin

Hello everyone,

I’m currently facing an issue embedding a custom class library into my Grasshopper plugin.

I’m embedding the DLL using the following snippet in my .csproj file:

Im embedding the dll

<ItemGroup Condition="'$(Configuration)' == 'Release' and '$(RhinoVersion)' == '8'">
    <EmbeddedResource
        Include="..\MyLibrary\bin\$(Configuration)\net7.0\MyLibrary.dll">
        <Link>Resources\MyLibrary.dll</Link>
        <LogicalName>MyPlugin.Resources.MyLibrary.dll</LogicalName>
    </EmbeddedResource>
    <EmbeddedResource
        Include="..\MyLibrary\bin\$(Configuration)\net48\MyLibrary.dll">
        <Link>Resources\MyLibrary.net48.dll</Link>
        <LogicalName>MyPlugin.Resources.MyLibrary.net48.dll</LogicalName>
    </EmbeddedResource>
</ItemGroup>

When inspecting the resulting .gha file with ILSpy, I can confirm that the DLL is embedded correctly.

To dynamically load the embedded DLL at runtime, I attempted to use a GH_AssemblyPriority class, but every approach so far leads to the following error when loading the plugin:

Path: C:\path\to\MyPlugin\bin\Release\net48\MyPlugin.gha  
Exception System.IO.FileNotFoundException:  
Message: Could not load file or assembly 'MyLibrary, Version=0.5.0.0, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.

Has anyone a suggestion were i might be wrong or another approach?

I think you need to read the resource as an byte array and use Reflection to load the assembly from this byte-array in-memory then. Doing so might be inefficient and can lead to false positives on antivirus. I would try to prevent this if there is not a good reason to do so.

Hey @TomTom thanks for your reply. Yea, I think I’m at that point where I will probably keep the DLL as external. Seams there are too many downsides.

Would you have a suggestion on how to keep my code private when including the DLL? I’m by no means an expert with this whole compiling and DLL stuff, but it seems fairly easy to access the logic in a DLL?

You can obfuscate a DLL by using various techniques. Same problem. If you apply too strong obfuscation methods, you might trigger antivirus or you introduce hidden bugs.

Basically you can just limited it to rename variables to shorter and more cryptic names. There are tools for it, and there are anti-obfuscator. But there is no way to revert a plausible renaming automatically.

I think lightweight obfuscation is okay for casual users to prevent understand the logic. Some developers write such code quite naturally. :wink:

Other than that, you should really ask yourself if its worth to protect the entire plugin. The more complex an application becomes, the less likely someone will just steal code, since understanding the application itself is challenging. But if you write tiny plugins mostly by calling library code, then I’m not so sure if its worth to protect, especially if a skilled person could reverse engineer the logic with ease.

Other than that, it is very common that in certain countries people just steal you intellectual property and then just republish it with their name. It happen to me, and it is one of the reasons why I’m not doing certain things anymore. So under this aspect, its worth to publish the source code on Github under MIT license and only think about protecting your intellectual property if you earn money with your software. Because only then it is worth to legally fight these people..

1 Like

One more thing. I’m not going to much in detail here. But in case you still want protect your code. I found it better to slightly alter the behaviour during runtime, instead of preventing people to “mis”-use my code. Introducing honeypots, strange bugs which, if reported, indicate someone did something with my code or introducing bugs that people loose interest in my tool.
Deception is better than denial. “It works on my p(ostal)c(ode).”

1 Like

Why are you embedding your DLLs at all? I would just ship them alongside your GHA

:sweat_smile:

Thanks very much for your inputs! Yeah the codebase is quite huge by now with only a few components and complexity is quite high.

So for now i decided to move the core logic into the same project as the GHA creation. Meaning the DLL is automatically in there somewhere!? without an actual Dll file. Probably im just shooting myself in the foot as soon as i will start the Rhino Plugin.

I worked on the logic in that dll now for months and since im not(yet?) open to open-source the whole thing, i would like to make it a bit more difficult to extract the logic if that makes sense.