RHI installer

I am getting close at “wrapping” up my small project.
And wanted to know how to make an installer file.
I see the information here about the cmd.py files.

But what about images that are used inside of the scripts? I have them right now in a sub folder “icons” is that how it should be done? Or does it need to live at the root?
Also how about the toolbar, and images associated with that?
How do you make that associated with a plugin? Do you somehow save that as a separate file from Rhino?

Hi @mikhail,

you can include files like images, toolbars etc. inside the folder structure of the rhi installer file. There is some information here.

I would recommend the RhinoScript PlugIn Compiler to create the rhp file from your python script. If you compile for Rhino 6 you’ll need to reference the RhinoCommon.dll of Rhino 6 in the PlugIn SDK settings.

To reference images, you’ll need to find out how to find them using the plugin installation path. I guess you’ll need relative paths so the compiled script can still find them.

I am trying to find how to add the images into the build
Inside of my scripts, they are all references

dir = os.path.dirname(__file__)
drawing.Bitmap(os.path.join(dir, 'icons', ImgDic.get(PartClass)))

So they do work relative.
But I cannot figure out how to add them to the project inside of compiler

This folder has 34 files in it, but since it’s not a .rhb or .py I cannot select them
If they need to exist at the root level overall I am fine with that even thou it’s a bit messy, but still, need a way to add them.
Also, how do I add the toolbar inside the compiler as well? Same issue, since the file is .rui
no way of seeing it…
Thanks for yout help!

Hi @mikhail,

you cannot add these files directly from the compiler yet. If you build the plugin, choose to create a rhi file. Once you have it, rename it to zip and add the files manually to the zip archive. If you need to support different versions or have compiled rhp files for multiple rhino versions, follow above guide for the required folder structure.

Once you added all files, rename it back to rhi.

Was able to get it to compile and get the toolbar “packaged” as per your suggestion.
I am not getting any of the commands to be found.
So I’ve looked around and seen that it is no longer in the python script folder, but rather in the overall plugin folder.
And I am not seeing anything there besides the .rhp and .rui as well as the icons folder (with all the stuff in it). Should I be putting in the _cmd.py files into that rhi/zip file?
Or am I missing something all together?
Did I still need to have the __plugin__.py file as per these instructions?

I did remove all of the RunCommand(True) type statements for all of the files.
I do not need any different rhino versions supports. It’s an in-house toolset to I just need to work on 6.10 (64bit) that came out today.

This is what it looked like after I ran the compiler in case it’s of a relevance

Hi @mikhail, you don’t need either of them. Just the script file is required. The name of the script becomes the registered command name. Example script:

import Rhino
def DoSomething():
   print "Hello World"


So does that mean if I’ve been making everything inside this

def RunCommand( is_interactive ):
	print "Running", __commandname__


I would need to either lose run def and call the function directly
Or actually have RunCommand() as my trigger to run the full command.
It sounds like _cmd should be stripped from the file names for sure.

Yes, just call TestViAttributesForm() directly.


Thank you for the information.
It seems like I am having issues with all but one scripts that are using eto. It would just freeze up rhino and kill itself after a short period of time.
I am sure it has a lot to do with the fact I am fresh as it can be at python (1 month into it). I am sure my code is just not 100% clean as it should be. But I was wondering if there are ways I can diagnose what is causing this problem, as it’s running as python script just fine.
Also to uninstall the plugin, do I just manually delete the root folder?

Found out what was causing the issues with all but 2 scripts. And those 2 scripts are at the core level have very similar code. So it’s really just the one that I need a way to identify what is causing the issues.
Also I just notices that each time you install it it makes a version folder. And the last 5 digits change every time.
something like this 1.0.6886.20917, 1.0.6886.15841, and also inside the plugin manager the version is set to Is there a way to control those numbers inside the compiler or before/after.
Thanks once again!

If you put the function codes of the ETO form in try: except: blocks, you might be able to find out where the error is. Also watch out for a crash bug file on the desktop, sometimes it is created, sometimes not.

Once you install (as single user), you should find the PlugIn and included files in this folder:


If you delete the folder, it should be gone. Usually if you then re-install, the location and guid of the PlugIn remains unchanged.

No i don’t think this is possible yet. It has been requested by @Jarek in the RhinoScriptCompiler thread. I include my version information in the load message to at least make sure the right version has been loaded properly.


1 Like

Thanks for the advice once again!
I am going to give it a try see if I can figure out how to fix it. :thinking:

I would not hold my breath :wink: The compiler project seems like a nobody’s child! Clement’s suggestion to include your version into the load message is a good path to follow.

1 Like

I think I’ve located the source of my issue… There might be more but this one overshadowing everything at the moment.
It is the OS module I am using to get file dir for locating supporting images for this plugin.

import os

directory = os.path.dirname(__file__)

As soon as I pull out the use of OS in the script things work…
Is there some other way to get the path? Or just have it look folder down in the directory it’s running from?
It looks like OS module doesn’t exist as a default installation with rhino’s python?
Or maybe something wrong with my syntax? Although it runs on the computer I am dev’ing this on… :thinking:
Could it be that the testing station I am using has 3.7 installed, and things are getting pulled differently?
Here is what I need it for, on a lot of images.

		image_btn_tubeRound = forms.ImageView()
		image_btn_tubeRound.Size = drawing.Size(imgSize, imgSize)
		image_btn_tubeRound.Image = drawing.Bitmap(os.path.join(directory, 'icons','btn_tubeRound.png'))

Hi @mikhail,

you might try below function to get the path of the compiled script which is now a plugin. Note that you’ll need to know if the plugin has been installed for one or all users, and specify the plugin name:

import Rhino
import scriptcontext
import rhinoscriptsyntax as rs

def GetPluginPath(plugin_name=None, autoload=True, all_user=False):
    """finds the full path of a plugin"""
    if not plugin_name: return 

    plugin_id = Rhino.PlugIns.PlugIn.IdFromName(plugin_name)
    rc, loaded, loadprotected = Rhino.PlugIns.PlugIn.PlugInExists(plugin_id)
    if not rc: return None

    if not loaded and autoload: Rhino.PlugIns.PlugIn.LoadPlugIn(plugin_id)

    plugin = Rhino.PlugIns.PlugIn.Find(plugin_id)
    if not plugin: return None

    if not all_user:
        return plugin.SettingsDirectory
        return plugin.SettingsDirectoryAllUsers

if __name__=="__main__":
    path = GetPluginPath(plugin_name="IronPython", autoload=True, all_user=False)
    if path: print path


If you are just trying to get the path to your plug-in, you could call
Rhino.PlugIns.PlugIn.PathFromName(string name)

Hi @stevebaer,

the problem with that method is that it reports plugins (and the path to that plugin) which may be installed in a different Rhino version than the one the method is called from. Eg. I have installed an old plugin named “FurGen”, it is installed in Rhino 4 and 5. If i call below from Rhino 5:

print Rhino.PlugIns.PlugIn.PathFromName("FurGen")

I get this path returned:

C:\Program Files (x86)\Rhinoceros 4.0\Plug-ins\FurGen\FurGen.rhp


Since my images are in a subfolder I am taking path and adding \icons\

myFullPath = path + '\\icons\\'
print 'myFullPath',myFullPath

Here is what I get

It’s getting the path corretly but adding settings subfolder before I am able to add the icons

Is the furgen that Rhino 5 knows about located in a different spot?

Hi @mikhail,

i guess you need to get the parent directory of the settings directory then:

import os.path
parent_path = os.path.abspath(os.path.join(path, os.pardir))
myFullPath = parent_path + '\\icons\\'
print 'myFullPath:', myFullPath