Document data question

I’ve added a class to a project based on the link below. Perhaps I’m over simplifying, but this test for Document Data, which I know is in the model, yields no data found. What am I missing?

Note: the document data was created in Rhino 5 using the following RhinoScript statement:
Rhino.SetDocumentData “RhinoStatics”, s & “_Name”, dlg.Name

    protected override Result RunCommand(RhinoDoc doc, RunMode mode)
    {
        RS2023_6_DocData docData= new RS2023_6_DocData();
        if (docData.Find("RhinoStatics") > 0)
        {
            int Count = docData.Find("RhinoStatics");
            RhinoApp.WriteLine("Found some (" + Count.ToString() + ")");
        }
        else
        {
            RhinoApp.WriteLine("Didn't find any");
            return Result.Failure;
        }
        return Result.Success;
    }

Hi @cestes001,

OK, I’m understanding the confusion.

Any plug-in and write and read it’s own private document data.

Rhino - Plugin User Data

RhinoScript, being a plug-in, write and reads document data (too). It exposes it’s document data to scripters in the form of the GetDocumentData and SetDocumentData methods.

Note, RhinoScript’s document data pre-dates Rhino’s document user text feature (RhinoScript as introduced in Rhino 2.0).

Since document user data is private and can only be written and read by the owning plug-in, we’ve been encouraging RhinoScirpt users to use GetDocumentUserText and GetDocumentUserText.

RhinoScript User Data Methods

That said, it is possible to access RhinoScript’s COM object and call functions on it from .NET.

For example:

protected override Result RunCommand(RhinoDoc doc, RunMode mode)
{
  Guid id = Rhino.PlugIns.PlugIn.IdFromName("RhinoScript");
  if (id == Guid.Empty)
    return Result.Failure;

  // The object returned by Rhino.RhinoApp.GetPlugInObject is a COM object.
  // So use the dynamic type, which is designed for COM Interop.
  dynamic rhinoScript = Rhino.RhinoApp.GetPlugInObject(id);
  if (null == rhinoScript)
    return Result.Failure;

  string section = "RhinoStatics";
  object[] objEntries = rhinoScript.GetDocumentData(section);
  if (null == objEntries)
  {
    RhinoApp.WriteLine("No RhinoScript document data \"{0}\" found.", section);
    return Result.Nothing;
  }

  foreach (object objEntry in objEntries)
  {
    string entry = objEntry.ToString();
    if (string.IsNullOrEmpty(entry)) 
      continue;

    object objValue = rhinoScript.GetDocumentData(section, entry);
    if (null == objValue)
      continue;

    string value = objValue.ToString();
    if (string.IsNullOrEmpty(value))
      continue;

    RhinoApp.WriteLine("\"{0}\" = \"{1}\".", entry, value);
  }

  return Result.Success;
}

Going forward, I’d highly encourage moving away from RhinoScript’s private user data features and either use what’s publicly available (object user text, document user text), or write and read your own user data.

Hope this helps.

– Dale

Thx. That makes sense and I’m really not interested in continuing the use of the data that was installed in the Rhino 5 RhinoScript/COM version of my plugin, except for maintaining those users that are “stuck” in the R5 world.

However, I need to add to add document data to new models in R6 and beyond, using the available code from the samples.

I just wanted to be sure I was correctly searching for existing data (assuming it was properly created) and the only document data I currently have available was that legacy stuff.

I don’t find a concrete example of how a plugin would create and store document data. I’ve managed object data, but that only goes so far.

Here’s what I have. Since the first run doesn’t find any data, it falls to the else clause to create some, which should then be available when the command is run a second time.

    protected override Result RunCommand(RhinoDoc doc, RunMode mode)
    {
        RS2023_6_DocData docData= new RS2023_6_DocData();
        if (docData.Find("RhinoStatics Shape;") > 0)
        {
            int Count = docData.Find("RhinoStatics Shape;");
            RhinoApp.WriteLine("Found some (" + Count.ToString() + ")");
        }
        else
        {
            docData.Add("RhinoStatics Shape;");
            RhinoApp.WriteLine("Didn't find any");
            return Result.Failure;
        }
        return Result.Success;
    }

Dale:

Thx for the chat this afternoon. As expected, I’m a bit overwhelmed, but I thought I’d try to bite off a little chunk at first.

I tried the code that retrieves my old RhinoScript document data.

When I plopped the snippet into my RunCommand(), I get a compiler error

|Error|CS0656|Missing compiler required member ‘Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create’|RS2023_6|C:\Development\Visual Studio 2022\Projects\Rhino\RhinoStatics2023\RS2023_6\RS2023_6_GetOldDocData.cs|29|Active|

at the following line with the word, “null” underlined.

        dynamic rhinoScript = Rhino.RhinoApp.GetPlugInObject(id);
        if (null == rhinoScript) <------ error location line 29
            return Result.Failure;

HI @cestes001,

Add a reference to Microsoft.CSharp to your project.

– Dale

That did it.

Now, im digging into SampleCsUserData and finding similar issues.

At the very top of the top level file there are 4 using clauses and they all give the same error.

“The type or namespace name ‘Rhino’ could not be found”.

The references include Microsoft. CSharp and RhinoCommon.

If you don’t have Rhino 7 installed, you can get this error, as some of the project’s reference the assemblies that come with Rhino 7. Other projects use the RhinoCommon NuGet package. I should probably update all of the RhinoCommon samples to use NuGet.

– Dale