I’ve been writing the Truss Plugin for almost 6 months now and I’ve realized that I need to have some global settings that the user can adjust. I’m still undecided on the best way to store this information whether in a text file or in the registry. I’ve found all sorts of various discussions on the topic but ultimately it has left me more confused as to the appropriate or best way to handle this. Can anyone give me a definitive answer on the best way to store persistent settings for a plugin.
most probably not…
Sketchup.write_default
and Sketchup.read_default
are there for this purpose, but do not always suit the use pattern of some plugins…
for example, if you run the same plugin at home and at work, and it has complex settings then many uses would prefer a ‘portable’ version of the settings…
this is why you see so many developers looking for an alternate location…
others have an export function that collects them using Sketchup.read_default
and write them to a text file, which can be emailed etc… and an import feature for storing on an alternate machine using Sketchup.write_default
…
so the real answer is what are your user expectations for the data you wish to store…
john
And have severe limitations and gotchas. The main gotcha is that every value read from the registry is immediately passed through the eval()
method.
But also save in the specific User SketchUp key (version-wise) that the extension is currently running under.
When the user next upgrades to say, SketchUp 2017, they’ll be crying for a settings “rollover”.
If you must go the registry route, use a library to read and write into a non-version specific “company” key, in “HKEY_CURRENT_USER\\Software
” or perhaps “HKEY_CURRENT_USER\\Software\\SketchUp\\Extensions
”. (You may need to cretae the “Extensions
” key before adding your “company” key, and your specific extension key below that.)
You can use the simple registry access methods of the Windows Script Host via the WIN32OLE
library, or the use the Win32::Registry
Ruby Standard Library.
The first way can be used on SketchUp < v14 (if the user has the “win32ole.so” file.) The second way is only SketchUp v14+.
Problem is this is platform specific.
So, the file option is likely a better choice. If you are dealing with only SketchUp v14+ running Ruby 2.0 or higher, then there is a standard library called PStore
.
http://www.rubydoc.info/stdlib/pstore/2.0.0/PStore
And the place to store version independent files would be:
company_folder = File.join( ENV["APPDATA"], "YourCompany" )
Dir.mkdir(company_folder) unless File.exist?(company_folder)
settings_file = File.join( company_folder, "YourExtension.dat" )
(Just an example, use whatever file extension, .pstore, .csv, etc., whatever makes sense.)
I don’t really care that the values are persistent across users or version, in fact I would rather they be unique for each user and for the SU version that way someone could have separate global settings for 2015 and 2016 of SU. All I really care about is that the settings are persistent across sessions.
What is the problem or concern with read values being passed through the eval() method?
Note, that I am not a very experienced Ruby or SketchUp programmer, I’ve only begun using the API and Ruby about 6 months ago and I only know enough to get me by, so bear with me.
from one of my old posts on SketchUcation:
I have noticed problems with the API’s
read_default()
on PC when it tries to readREG_SZ
strings values. We need to store quotes with the value in the registry. Using the inspect() method is a good idea, because it will escape embedded ’ or " if used for unit symbols.
If I try to read the “SnapLength” attribute in the “Preferences” key, I getnil
, because it’s set to 1" instead of ‘1"’ or “1"”
Also it cannot see any keys with spaces in their names, and just returns nil
.
There are quite a few threads over there where we discuss the quirks and limitations of using the registry for settings. You’ll have to do a search over there for more.
OK, then, it’s most likely you’ll need to use the API methods (because it is the easiest way,) and experience the quirks and limitations, and learn the hard way like we did.
So the best advice is to use the API “defaults” methods defensively (within a begin
… rescue
block) to trap for erroneous reads. You should not have any problems with simple numeric types, or plain strings (just use .inspect
when you write them to the registry so their quotes are escaped.)