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.
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
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 🙂
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
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.
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!
Well, due too lack of time I was hoping someone had a working example by now 🙂
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 🙂
@Anonymous,
I have the same issue. Any updates on this topic?
Regards,
Yes, I provided an update on this topic in July 2017:
Cheers,
Jeremy
@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
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..
@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?
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.
Thanks.
Regards,
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:
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.
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:
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.
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.
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.
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; } } }
Can't find what you're looking for? Ask the community or share your knowledge.