Announcements
Attention for Customers without Multi-Factor Authentication or Single Sign-On - OTP Verification rolls out April 2025. Read all about it here.

Dynamo script in Revit API

Anonymous

Dynamo script in Revit API

Anonymous
Not applicable

Hi,

 

Does anyone know where I can find the code to run a dynamo script from within the Revit API ? I want to write a C# add-in that can run a dynamo script in the background. I know there is dyno browser, so there is a way to acchieve this. I just can't figure out how.

 

 

Reply
12,570 Views
33 Replies
Replies (33)

jeremytammik
Autodesk
Autodesk

Dear Remy,

 

Thank you for your query.

 

This is certainly possible, and might even be pretty easy if you have the right bits and pieces to put together.

 

I don't.

 

Basically, you can run any .NET language from within any other .NET language using the runtime language interpretation, compilation and execution facilities it provides.

 

You might want to discuss this kind of topic directly with the Revit Python Shell and Dynamo communities.

 

They probably have the tools you could use to implement this ready and waiting for you.

 

Please let us know how you end up solving this.

 

Thank you!

 

I hope this helps.

 

Best regards,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes

Anonymous
Not applicable

Hmm, since Autodesk is pushing Dynamo so much, I assumed there would be code examples to do so already, byt apperently not 😞

 

Ain't this a nice topic for the building coder 🙂

 

 

0 Likes

Revitalizer
Advisor
Advisor

Hi Remy,

 

Dynamo is open source, so you could learn to interprete or execute *.dyn files by browsing the C# project:

https://github.com/DynamoDS/Dynamo

 

 

Cheers,

Rudi




Rudolf Honke
Software Developer
Mensch und Maschine





0 Likes

Anonymous
Not applicable

Now in Revit 2017.1 revit is equiped with a dynamo player, so apperently someone at autodesk knows how to run dynamo scripts in the revit api.

 

Does anybody know how I can make my own button in reivt (or the ribbon) that runs a specific dynamo script.

 

0 Likes

jeremytammik
Autodesk
Autodesk

As Rudi pointed out, anybody who takes a look at the open source repo should be able to tell you. How about taking a peek yourself? Greetings from AU!



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes

Anonymous
Not applicable

Well, due too lack of time I was hoping someone had a working example by now 🙂

 

0 Likes

dante.van.wettum
Advocate
Advocate

I am too, very much looking for this (but already working on too many things at the same time to dive into it atm).

Please keep us updated when you find out more about this subject 🙂

0 Likes

Organon
Advisor
Advisor

@Anonymous,

 

I have the same issue. Any updates on this topic?

 

Regards,


Arquitectura | Análisis CAD & BIM | Diseño Paramétrico | Programación
BIM-METADATA | LinkedIn | YouTube
0 Likes

jeremytammik
Autodesk
Autodesk

Yes, I provided an update on this topic in July 2017:

 

https://forums.autodesk.com/t5/revit-api-forum/how-to-open-dynamo-file-through-revit-addin/td-p/7016...

 

Cheers,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes

jeremytammik
Autodesk
Autodesk

@Anonymous did you ever end up implementing this? Do you have a sample handy? I would gladly publish it for you  🙂  Thank you! Cheers, Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes

Anonymous
Not applicable

Hi Jeremy, Due too time and other priorities I never continued with this topic. With the comming of dynamo player I was hoping the Revit API would be expanded with some related commands/methods aswell. Unfortunately it appears not to be so..

 

 

dante.van.wettum
Advocate
Advocate

@Anonymous

Looking at the original idea on the ideastation, i believe that was the setup of that idea.

Hopefully they will implement such a thing, or a new ideastation item is needed?

 

@jeremytammik

You mentioned to simulate a mouseclick, but i dont think this will work in combination with the dynamo player; e.g. filling in parameters and executing the right script in the list.

Organon
Advisor
Advisor

@jeremytammik,

 

Thanks.

 

Regards,


Arquitectura | Análisis CAD & BIM | Diseño Paramétrico | Programación
BIM-METADATA | LinkedIn | YouTube
0 Likes

LeeFried
Contributor
Contributor

I am now working on this. I think I've found where Dynamo runs the code, but it does not work when I replicate it. The portion I found in the Git is in the IronPythonEvaluator.cs:

 

public static object EvaluateIronPythonScript(
            string code,
            IList bindingNames,
            [ArbitraryDimensionArrayImport] IList bindingValues)
{
    // TODO - it would be nice if users could modify a preference
    // setting enabling the ability to load additional paths

    // Container for paths that will be imported in the PythonEngine
    List<string> paths = new List<string>();

    // Attempt to get the Standard Python Library
    string stdLib = pythonStandardLibPath();

    if (code != prev_code)
    {
        ScriptEngine PythonEngine = Python.CreateEngine();
        if (!string.IsNullOrEmpty(stdLib))
        {
            code = "import sys" + System.Environment.NewLine + code;
            paths = PythonEngine.GetSearchPaths().ToList();
            paths.Add(stdLib);
        }

        // If any paths were successfully retrieved, append them
        if (paths.Count > 0)
        {
            PythonEngine.SetSearchPaths(paths);
        }

        ScriptSource script = PythonEngine.CreateScriptSourceFromString(code);
        script.Compile();
        prev_script = script;
        prev_code = code;
    }

    ScriptEngine engine = prev_script.Engine;
    ScriptScope scope = engine.CreateScope();

    int amt = Math.Min(bindingNames.Count, bindingValues.Count);

    for (int i = 0; i < amt; i++)
    {
        scope.SetVariable((string)bindingNames[i], InputMarshaler.Marshal(bindingValues[i]));
    }

    try
    {
        OnEvaluationBegin(engine, scope, code, bindingValues);
        prev_script.Execute(scope);
    }
    catch (Exception e)
    {
        OnEvaluationEnd(false, engine, scope, code, bindingValues);
        var eo = engine.GetService<ExceptionOperations>();
        string error = eo.FormatException(e);
        throw new Exception(error);
    }

    OnEvaluationEnd(true, engine, scope, code, bindingValues);

    var result = scope.ContainsVariable("OUT") ? scope.GetVariable("OUT") : null;

    return OutputMarshaler.Marshal(result);
}

 

I'm hitting a roadblock, though. All namespaces loaded, no compile errors or warnings. I've simplified mine to:

 

[Transaction(TransactionMode.Manual)]
public class ModelCleanup : IExternalCommand
{
    public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
    {
        string code = @"|filepath|.dyn";
        ScriptEngine engine = Python.CreateEngine();
        ScriptScope scope = engine.CreateScope();
        ScriptSource script = engine.CreateScriptSourceFromFile(code);
        script.Compile();
        script.Execute(scope);

        return Result.Succeeded;
    }

I end up with the following error:

Capture.JPG

Does anyone have any insight? I am already using Dyno Browser, though I'm not 100% happy with it. I cannot decompile his DLL's to a far-enough degree to see how he's doing it, but he proves it's possible. I do not like Dynamo Player at all. I'm simply looking for a way to have C# call some .dyn files so I don't have to waste time rewriting them all.

0 Likes

LeeFried
Contributor
Contributor

Full code is ("|filepath|" is a substitute):

#region Namespaces
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Microsoft.Scripting.Hosting;
using IronPython.Hosting;
#endregion

namespace RATCommands
{
    [Transaction(TransactionMode.Manual)]
    public class ModelCleanup : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            string code = @"|filepath|.dyn";
            ScriptEngine engine = Python.CreateEngine();
            ScriptScope scope = engine.CreateScope();
            ScriptSource script = engine.CreateScriptSourceFromFile(code);
            script.Compile();
            script.Execute(scope);

            return Result.Succeeded;
        }
    }
}

I re-referenced my Microsoft.Scripting.dll to that from the ProgramData\Autodesk\Revit\ folder and now I get the following error:

Capture.JPG

0 Likes

LeeFried
Contributor
Contributor

I've managed to get it to attempt to execute a python script...only to come to the realization that the files are .dyn and are not python scripts.

 

DUH

 

Back to the drawing board.

0 Likes

jeremytammik
Autodesk
Autodesk

Doesn't the DYN file contain the Python script as text?

 

You might be able to parse the DYN, extract the pure Python, and execute that as desired.

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes

LeeFried
Contributor
Contributor

That was my first thought, so I tried

var pyCode = Path.ChangeExtension(code, ".py");
var engine = Python.CreateRuntime();
dynamic scope = engine.UseFile(pyCode);
scope.Simple()

but that didn't work either.

0 Likes

Kevin.Lawson.PE
Advocate
Advocate

Hi Lee,

 

Did you see this post: Open Dynamo in background while C# add-in executes  ?

 

I feel like hzamaniM54WP was close with the following code, but I can't figure out what he was doing wrong either.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Dynamo.Applications;
using Dynamo.Core;

namespace my_addin
{
    [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
    class DynamoTest : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {


            string Journal_Dynamo_Path = path_to_my_dyn_file;
            DynamoRevit dynamoRevit = new DynamoRevit()

            DynamoRevitCommandData dynamoRevitCommandData = new DynamoRevitCommandData();
            dynamoRevitCommandData.Application = commandData.Application;
            IDictionary<string, string> journalData = new Dictionary<string, string>
            {
                { Dynamo.Applications.JournalKeys.AutomationModeKey, true.ToString() },
                { Dynamo.Applications.JournalKeys.ShowUiKey, false.ToString() },
                { Dynamo.Applications.JournalKeys.DynPathKey, Journal_Dynamo_Path }
            };
            dynamoRevitCommandData.JournalData = journalData;       

            Result externalCommandResult = dynamoRevit.ExecuteCommand(dynamoRevitCommandData);

            return externalCommandResult;



        }
    }
}

Error.png

 

 

-Kevin Lawson, PE
www.rippleengineeringsoftware.com
Revit heating and cooling load calculations in one click!
0 Likes