Hi All,
As far as I know, ghuser files won’t be loaded from outside of “%appdata%\Grasshopper\UserObjects”.
Is it possible to do it like gha file linked by ghlink?
Thanks,
Mingbo
Hi All,
As far as I know, ghuser files won’t be loaded from outside of “%appdata%\Grasshopper\UserObjects”.
Is it possible to do it like gha file linked by ghlink?
Thanks,
Mingbo
It looks like in Grasshopper accepts more than one folder for loading userobjects from Grasshopper.Folders.UserObjectFolders.
How can we add anew folder to the current folder list before loading an instance of the Grasshopper? It’s currently the default UserObjects folder and one random folder which is added by Weaverbird plugin. I’m not sure how/when the second one has been added.
This might potentially work (haven’t tested), but this is how Ironbug loads openstudio.dll. This is executed when GH is loading.

Never mind, adding userObjectFolders under PriorityLoad() doesn’t work.
Did you ever figure this out?
The Pancake plug-in will give you options to load user objects elsewhere.
That won’t do because UserObjectFolders is generated per call and never reflected back into GH.
Any news on that?
In case anyone else is still trying to do this, I’ve found a workaround which works for our case of trying to create a way of sharing user objects between people in our company.
This works by copying the .ghuser files you would like to share from a shared drive to the local system. The key is where the copying script runs. I’ve only be able to get this work by subscribing to the DocumentAdded event by using the PriorityLoad method in GH_AssemblyPriority. You have to build this into a plugin for it run. But that plugin can be loaded through a .ghlink. The user objects will be copied access each time a new document is opened.
This probably isn’t the best way to do it as your altering files which are actively being used by grasshopper but it seems to work for us without any issues. I’ve tried running the code as part of the CanvasCreatedEventHandler or directly in PriorityLoad but although the user objects get copied they don’t get populated to the components cache. My best bet is this is due to the order of operations when grasshopper is loaded.
Adding this class to a plugin will enable the functionality.
using Grasshopper;
using Grasshopper.GUI.Canvas;
using Grasshopper.Kernel;
using Rhino;
using System;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
namespace UserObjectsRefresh
{
public class UserObjectsRefresh : Grasshopper.Kernel.GH_AssemblyPriority
{
public override Grasshopper.Kernel.GH_LoadingInstruction PriorityLoad()
{
//refresh user objects when a new document is added.
//I've tried adding this to canvas created event but although it copies the files they are not populated into the components.
//The same thing also happens when you run the code directly in Priority load.
Instances.DocumentServer.DocumentAdded += RefreshUserObjectsEvent;
return GH_LoadingInstruction.Proceed;
}
private void RefreshUserObjectsEvent(GH_DocumentServer sender, GH_Document doc)
{
// add date time stamp to rhino window to know when has run.
RhinoApp.WriteLine("______Refreshing Shared User Objects: " + DateTime.Now.ToString());
//set paths for where new files are read from, and where user objects are added.
string sourcePath = "G:\\Shared drives\\UserObjects";
string targetPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Grasshopper\\UserObjects";
//set prefix for the local user objects so they can be identifed and removed.
string prefix = "FMT_";
//create targetPath if it doesn't already exist
if (!System.IO.Directory.Exists(targetPath))
{
Directory.CreateDirectory(targetPath);
RhinoApp.WriteLine("created userobjects folder");
}
//clean out existing user objects so that new objects can the added without any clash issues.
string[] FilePaths = Directory.GetFiles(targetPath);
foreach (string filePath in FilePaths)
{
string filename = Path.GetFileName(filePath);
if (filename.Contains(prefix))
{
File.Delete(filePath);
RhinoApp.WriteLine(filename + " has been deleted");
}
}
//copy in new userobjects
RhinoApp.WriteLine("copying fresh set of userobjects");
string fileName = string.Empty;
string destFile = string.Empty;
// To copy all the files in one directory to another directory.
if (System.IO.Directory.Exists(sourcePath))
{
string[] files = System.IO.Directory.GetFiles(sourcePath);
// Copy the files and overwrite destination files if they already exist.
foreach (string s in files)
{
// Use static Path methods to extract only the file name from the path.
fileName = System.IO.Path.GetFileName(s);
//create new path with prefix
destFile = System.IO.Path.Combine(targetPath, prefix + fileName);
//copy file from existing path to new path.
System.IO.File.Copy(s, destFile, true);
RhinoApp.WriteLine("copied file: " + fileName);
}
}
else
{
RhinoApp.WriteLine("SOURCE PATH DOES NOT EXIST! - Check you can access" + sourcePath.ToString());
}
}
}
}