Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Dynamo script in Revit API

32 REPLIES 32
Reply
Message 1 of 33
Anonymous
11743 Views, 32 Replies

Dynamo script in Revit API

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.

 

 

32 REPLIES 32
Message 2 of 33
jeremytammik
in reply to: Anonymous

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

Message 3 of 33
Anonymous
in reply to: jeremytammik

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 🙂

 

 

Message 4 of 33
Revitalizer
in reply to: Anonymous

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





Message 5 of 33
Anonymous
in reply to: Revitalizer

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.

 

Message 6 of 33
jeremytammik
in reply to: Anonymous

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

Message 7 of 33
Anonymous
in reply to: jeremytammik

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

 

Message 8 of 33
dante.van.wettum
in reply to: Anonymous

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 🙂

Message 9 of 33
Organon
in reply to: Anonymous

@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
Message 10 of 33
jeremytammik
in reply to: Organon

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

Message 11 of 33
jeremytammik
in reply to: Anonymous

@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

Message 12 of 33
Anonymous
in reply to: jeremytammik

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..

 

 

Message 13 of 33
dante.van.wettum
in reply to: Anonymous

@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.

Message 14 of 33
Organon
in reply to: jeremytammik

@jeremytammik,

 

Thanks.

 

Regards,


Arquitectura | Análisis CAD & BIM | Diseño Paramétrico | Programación
BIM-METADATA | LinkedIn | YouTube
Message 15 of 33
LeeFried
in reply to: Organon

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.

Message 16 of 33
LeeFried
in reply to: LeeFried

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

Message 17 of 33
LeeFried
in reply to: LeeFried

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.

Message 18 of 33
jeremytammik
in reply to: LeeFried

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

Message 19 of 33
LeeFried
in reply to: jeremytammik

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.

Message 20 of 33
Kevin.Lawson.PE
in reply to: LeeFried

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!

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report