diff --git a/src/AssemblySharedInfoGenerator/AssemblyInfoGenerator.csproj b/src/AssemblySharedInfoGenerator/AssemblyInfoGenerator.csproj
index c9a83b7643..53258bb055 100644
--- a/src/AssemblySharedInfoGenerator/AssemblyInfoGenerator.csproj
+++ b/src/AssemblySharedInfoGenerator/AssemblyInfoGenerator.csproj
@@ -9,10 +9,12 @@
false
false
"$(SolutionDir)transform_all.bat" "$(ProjectDir)"
+ false
bin\
false
None
AssemblyInfoGenerator
+ bin\$(Configuration)\
false
diff --git a/src/BUILDSYSTEM_TODO.md b/src/BUILDSYSTEM_TODO.md
new file mode 100644
index 0000000000..16e424ec3d
--- /dev/null
+++ b/src/BUILDSYSTEM_TODO.md
@@ -0,0 +1,106 @@
+# Build System Cleanup — Open Questions & TODOs
+
+These are known issues and open design questions in the build system that need
+to be resolved, particularly for the `D4R_DA_2026` branch targeting Revit 2026 / net8.
+
+---
+
+## 1. Platform naming is confusing and redundant
+
+`CS_SDK.props` defines three platforms:
+
+| Platform | TargetFramework | Notes |
+|------------|---------------------|-------|
+| `NET80` | `net8.0-windows` | Interactive Revit build |
+| `NET10_DA` | `net8.0-windows` | **Same as NET80 — name implies net10 but it's net8** |
+| `NET100` | `net10.0-windows` | Future Revit targeting net10 |
+
+For the `D4R_DA_2026` branch (Revit 2026), only `net8.0-windows` is relevant.
+`NET100` adds noise and `NET10_DA` is actively misleading.
+
+**Important:** `_DA` in the platform name is a meaningful build profile — it is not just a
+TFM alias. Any platform whose name contains `_DA` triggers these behaviours across multiple projects:
+
+| Project | What `_DA` removes |
+|---|---|
+| `CS_SDK.props` | Defines `DESIGN_AUTOMATION` compile constant |
+| `DynamoRevit.csproj` | Removes `DynamoRevit.cs`, `DynamoRevitApp.cs`, entire `ViewModel/` (interactive startup + ribbon) |
+| `RevitNodesUI.csproj` | Removes all WPF controls, selection dialogs, XAML pages |
+| `RevitServices.csproj` | Removes `Threading/*.cs` (UI thread marshalling, not needed in headless DA) |
+
+So the `_DA` suffix carries real semantic weight. The problem is solely the `NET10` prefix,
+which implies net10 when the TFM is actually net8. Renaming `NET10_DA` → `NET80_DA` everywhere
+would fix the confusion without changing any build behaviour.
+
+**Questions:**
+- Should `D4R_DA_2026` drop `NET100` entirely and only expose `NET80`?
+- Was `NET10_DA` ever actually net10 and got downgraded, or has it always been net8?
+- Should DA just use `NET80` with a separate property/flag to denote DA vs interactive,
+ rather than a separate platform name?
+- If `NET10_DA` stays, should it be renamed (e.g. `NET80_DA`) to reflect actual TFM?
+
+---
+
+## 2. Solution file responsibilities are unclear
+
+| Solution | Projects included | Typical build command |
+|-----------------------|--------------------------------|-----------------------|
+| `DynamoRevit.DA.sln` | DADynamoApp + deps only | `/p:Platform=NET10_DA` |
+| `DynamoRevit.All.sln` | Everything incl. tests | `/p:Platform=NET80` or `NET100` |
+
+`DADynamoApp` is **not** listed explicitly in `All.sln` — it is pulled in as a
+transitive project reference from `RevitSystemTests`. This causes the solution to
+build it without a proper platform mapping, which leads to build errors under
+`dotnet build` with .NET SDK 10 (see issue 3 below).
+
+A workaround was added: explicit `DADynamoApp` entry in `All.sln` mapping
+`NET80`/`NET100` → `NET10_DA`. But this is a band-aid.
+
+**Questions:**
+- Should `DADynamoApp` be a first-class explicit project in `All.sln`?
+- Should `DA.sln` be a proper subset configuration of `All.sln`, or kept fully separate?
+- Is there a reason DA uses `NET10_DA` platform instead of `NET80`? If not, unify them
+ and remove the extra platform.
+
+---
+
+## 3. `dotnet build` vs VS MSBuild inconsistency
+
+`DynamoRevit.All.sln` builds cleanly with VS MSBuild:
+```
+& "C:\Program Files\Microsoft Visual Studio\18\Professional\MSBuild\Current\Bin\MSBuild.exe" DynamoRevit.All.sln -p:Configuration=Debug -p:Platform=NET80 -m
+```
+
+But fails with `dotnet build` using .NET SDK 10:
+```
+dotnet build DynamoRevit.All.sln -c Debug /p:Platform=NET80
+```
+
+Two known `dotnet build`-only failures:
+
+**a) `DADynamoApp` — `MSB3992: 'RootElementName' is not set`**
+- Root cause: `EnableDynamicLoading=true` causes SDK 10 to set
+ `UseAttributeForTargetFrameworkInfoPropertyNames=true`, which requires
+ `RootElementName` to be set explicitly. VS MSBuild does not have this requirement.
+- Possible fixes: set `false`,
+ or set `DADynamoApp` explicitly.
+
+**b) `DynamoRevitIcons` — `ResGen.exe not supported on .NET Core MSBuild`**
+- Pre-existing issue. The `.resx` code generation step uses ResGen.exe which is
+ not available in the .NET Core MSBuild toolchain.
+- Possible fix: migrate resource generation to use `` without
+ ResGen, or exclude from `dotnet build` paths.
+
+**Question:** Is `dotnet build` a supported/required path in CI, or does CI always
+use VS MSBuild? The `Jenkinsfile` delegates to `DynamoRevitUtils` — need to check
+those build scripts to confirm.
+
+---
+
+## 4. Research needed / action items
+
+- [ ] Check `DynamoRevitUtils` Jenkins scripts: which solution, which platform, `dotnet` or VS MSBuild?
+- [ ] Confirm whether `NET100` is used in any CI job for this branch
+- [ ] Decide on NET10_DA rename/merge with NET80
+- [ ] Decide whether All.sln should be the canonical "build everything" solution
+- [ ] Fix `dotnet build` compatibility if CI requires it (MSB3992 + ResGen)
diff --git a/src/Config/CS_SDK.props b/src/Config/CS_SDK.props
index f4df74e1b9..655026b85f 100644
--- a/src/Config/CS_SDK.props
+++ b/src/Config/CS_SDK.props
@@ -4,11 +4,12 @@
x64
false
- NET80;NET100
+ NET80;NET10_DA;NET100
net8.0-windows
+ net8.0-windows
net10.0-windows
17.0
- Preview Release
+ 2026
$(SolutionDir)packages
$(SolutionDir)..\extern
$(SolutionDir)..\lib\Revit $(RevitVersionNumber)\$(DCoreLibSubFolder)
@@ -40,9 +41,13 @@
true
TRACE
+
+ $(DefineConstants);DESIGN_AUTOMATION
+
false
+ all
diff --git a/src/Config/packages_versions.props b/src/Config/packages_versions.props
index 8dee173b3b..2187ff04b4 100644
--- a/src/Config/packages_versions.props
+++ b/src/Config/packages_versions.props
@@ -2,7 +2,7 @@
- 4.0.0-beta2972
+ 3.5.0.8300
$(DYNAMOCORE_VERSION)
$(DYNAMOCORE_VERSION)
@@ -13,8 +13,8 @@
net10.0
3.0.1.4707
- 4.0.9405.33709
- net10.0
+ 3.0.9229.39980
+ net8.0
1.2.2
diff --git a/src/DADynamoApp/DAApplication.cs b/src/DADynamoApp/DAApplication.cs
new file mode 100644
index 0000000000..834c3415c8
--- /dev/null
+++ b/src/DADynamoApp/DAApplication.cs
@@ -0,0 +1,63 @@
+
+using Autodesk.Revit.ApplicationServices;
+using Autodesk.Revit.DB;
+using System.Diagnostics;
+using System.Reflection;
+
+namespace DADynamoApp
+{
+ [Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
+ [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
+ public class DAApplication : IExternalDBApplication
+ {
+ private string ParentPath;
+ private string CurrentDirectory;
+ private readonly string PythonDllFolder = "pythonDependencies";
+
+ private DAEntrypoint daEntryPoint;
+
+ public ExternalDBApplicationResult OnShutdown(ControlledApplication application)
+ {
+ AppDomain.CurrentDomain.UnhandledException -= CurrentDomain_UnhandledException;
+ AppDomain.CurrentDomain.ProcessExit -= CurrentDomain_ProcessExit;
+ AppDomain.CurrentDomain.AssemblyResolve -= CurrentDomain_AssemblyResolve;
+ return daEntryPoint.OnShutdown(application);
+ }
+
+ public ExternalDBApplicationResult OnStartup(ControlledApplication application)
+ {
+ AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
+ AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
+ AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
+
+ CurrentDirectory = Directory.GetCurrentDirectory();
+ ParentPath = Directory.GetParent(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)).FullName;
+
+ Console.WriteLine("<> Starting to load DAEntrypoint");
+
+ daEntryPoint ??= new DAEntrypoint();
+
+ return daEntryPoint.OnStartup(application);
+ }
+
+ private static void CurrentDomain_ProcessExit(object? sender, EventArgs e)
+ {
+ Process proc = Process.GetCurrentProcess();
+ Console.WriteLine($"Dynamo exiting with Peak physical memory {proc.PeakWorkingSet64} bytes");
+ if (proc.HasExited)
+ {
+ Console.WriteLine($"Dynamo exiting with code {proc.ExitCode}");
+ }
+ }
+
+ private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
+ {
+ Console.WriteLine($"Unhandled exception: {e}");
+ }
+
+ private Assembly? CurrentDomain_AssemblyResolve(object? sender, ResolveEventArgs args)
+ {
+ return DynamoRevitAssemblyResolver.ResolveDynamoAssembly(ParentPath, [Path.Combine(CurrentDirectory, PythonDllFolder)], args);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/DADynamoApp/DADynamoApp.csproj b/src/DADynamoApp/DADynamoApp.csproj
new file mode 100644
index 0000000000..c9631efb7a
--- /dev/null
+++ b/src/DADynamoApp/DADynamoApp.csproj
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+ enable
+ enable
+ false
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+ $(REVITAPI)\RevitAPI.dll
+ False
+
+
+
+
+
+
+
+
+ runtime
+
+
+
+
+
+
+
+
+
+ $(PkgDynamoPlayer)\bin\Release\net8.0\bin\DynamoPlayer.Models.dll
+ False
+
+
+ $(PkgDynamoPlayer)\bin\Release\net8.0\bin\DynamoPlayer.Server.dll
+ False
+
+
+ $(PkgDynamoPlayer)\bin\Release\net8.0\bin\DynamoPlayer.Workflows.dll
+ False
+
+
+
+
+
+
diff --git a/src/DADynamoApp/DAEntrypoint.cs b/src/DADynamoApp/DAEntrypoint.cs
new file mode 100644
index 0000000000..31eafcd84f
--- /dev/null
+++ b/src/DADynamoApp/DAEntrypoint.cs
@@ -0,0 +1,565 @@
+using Autodesk.DataManagement;
+using Autodesk.DataManagement.Model;
+using Autodesk.Revit.ApplicationServices;
+using Autodesk.Revit.DB;
+using DesignAutomationFramework;
+using DSCPython;
+using Dynamo.Applications;
+using Dynamo.Graph.Nodes;
+using Dynamo.Graph.Workspaces;
+using Dynamo.Migration;
+using Dynamo.Models;
+using Dynamo.PythonServices;
+using Dynamo.Scheduler;
+using DynamoPlayer;
+using Greg.AuthProviders;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using ProtoCore.DesignScriptParser;
+using RevitServices.Elements;
+using RevitServices.Persistence;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.Loader;
+using System.Text.RegularExpressions;
+using System.Windows.Controls;
+using static Dynamo.Models.DynamoModel;
+
+namespace DADynamoApp
+{
+ public class DAEntrypoint
+ {
+ private DynamoModel model;
+ internal static DynamoPlayerLoggerConfiguration logConfig = new DynamoPlayerLoggerConfiguration() { DynamoLogLevel = Dynamo.Logging.LogLevel.Console, LogLevel = DynamoPlayer.LogLevel.Information };
+ private string DynamoPath;
+ private string DynamoRevitPath;
+ private ControlledApplication controlledApplication;
+
+ // Store event handler references for cleanup
+ private readonly Dictionary evaluationStartedHandler,
+ EventHandler evaluationCompletedHandler,
+ Dictionary[]> nodeHandlers)>
+ workspaceHandlers = [];
+
+ private string LoadMessage;
+ private string WorkItemFolder;
+ private readonly string PythonDllFolder = "pythonDependencies";
+
+
+ private List Updaters = [];
+
+ public ExternalDBApplicationResult OnShutdown(ControlledApplication application)
+ {
+ model?.Dispose();
+
+ controlledApplication.DocumentClosing -= RevitServices.EventHandler.EventHandlerProxy.Instance.OnApplicationDocumentClosing;
+ controlledApplication.DocumentClosed -= RevitServices.EventHandler.EventHandlerProxy.Instance.OnApplicationDocumentClosed;
+ controlledApplication.DocumentOpened -= RevitServices.EventHandler.EventHandlerProxy.Instance.OnApplicationDocumentOpened;
+
+ return ExternalDBApplicationResult.Succeeded;
+ }
+
+ public ExternalDBApplicationResult OnStartup(ControlledApplication application)
+ {
+ controlledApplication = application;
+
+ WorkItemFolder = Directory.GetCurrentDirectory();
+ Console.WriteLine($"<> Work folder is '{WorkItemFolder}'");
+
+ DynamoRevitPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
+ DynamoPath = Directory.GetParent(DynamoRevitPath).FullName;
+
+ var hostloc = typeof(Autodesk.Revit.ApplicationServices.Application).Assembly.Location;
+ var hostDir = Path.GetDirectoryName(hostloc);
+
+ Console.WriteLine("<> Starting to load D4DA");
+
+ try
+ {
+ RevitServicesUpdater.Initialize(Updaters);
+ Console.WriteLine("<> D4DA Loaded");
+
+ RevitServices.Transactions.TransactionManager.SetupManager(new RevitServices.Transactions.AutomaticTransactionStrategy());
+ // TODO: do we need element binding in Design Automations?
+ ElementBinder.IsEnabled = true;
+
+ controlledApplication.DocumentClosing += RevitServices.EventHandler.EventHandlerProxy.Instance.OnApplicationDocumentClosing;
+ controlledApplication.DocumentClosed += RevitServices.EventHandler.EventHandlerProxy.Instance.OnApplicationDocumentClosed;
+ controlledApplication.DocumentOpened += RevitServices.EventHandler.EventHandlerProxy.Instance.OnApplicationDocumentOpened;
+
+ DesignAutomationBridge.DesignAutomationReadyEvent += HandleDesignAutomationReadyEvent;
+
+ return ExternalDBApplicationResult.Succeeded;
+ }
+ catch (Exception ex)
+ {
+ return ExternalDBApplicationResult.Failed;
+ }
+ }
+
+ private static string GetRevitContext(Autodesk.Revit.ApplicationServices.Application app)
+ {
+ var r = new Regex(@"\b(Autodesk |Structure |MEP |Architecture )\b");
+ return r.Replace(app.VersionName, "");
+ }
+
+ ///
+ /// Extracts the 'token' value from the work item JSON content.
+ /// This is robust to casing differences and supports BoundArguments as an object.
+ /// Returns null if token cannot be found.
+ ///
+ private string? ExtractTokenFromWorkItem(string workItemContent)
+ {
+ if (string.IsNullOrWhiteSpace(workItemContent)) return null;
+
+ try
+ {
+ var job = JObject.Parse(workItemContent);
+
+ // Find BoundArguments (case-insensitive)
+ JToken? boundToken = null;
+ if (!job.TryGetValue("BoundArguments", out boundToken))
+ {
+ foreach (var prop in job.Properties())
+ {
+ if (string.Equals(prop.Name, "BoundArguments", StringComparison.OrdinalIgnoreCase))
+ {
+ boundToken = prop.Value;
+ break;
+ }
+ }
+ }
+
+ if (boundToken == null) return null;
+
+ // If it's an object, try direct lookup
+ if (boundToken.Type == JTokenType.Object)
+ {
+ var boundObj = (JObject)boundToken;
+
+ // try exact key 'token' then case-insensitive
+ if (boundObj.TryGetValue("adsk3LeggedToken", out var tokVal))
+ {
+ return tokVal.Type == JTokenType.String ? tokVal.Value() : tokVal.ToString();
+ }
+
+ foreach (var prop in boundObj.Properties())
+ {
+ if (string.Equals(prop.Name, "adsk3LeggedToken", StringComparison.OrdinalIgnoreCase))
+ {
+ return prop.Value.Type == JTokenType.String ? prop.Value.Value() : prop.Value.ToString();
+ }
+ }
+ }
+
+ // Fallback: convert to dictionary and search case-insensitively
+ var boundDict = boundToken.ToObject>();
+ if (boundDict != null)
+ {
+ foreach (var kv in boundDict)
+ {
+ if (string.Equals(kv.Key, "adsk3LeggedToken", StringComparison.OrdinalIgnoreCase))
+ {
+ return kv.Value.Type == JTokenType.String ? kv.Value.Value() : kv.Value.ToString();
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"ExtractTokenFromWorkItem failed: {ex.Message}");
+ }
+
+ return null;
+ }
+
+ public void HandleDesignAutomationReadyEvent(object sender, DesignAutomationReadyEventArgs e)
+ {
+ Console.WriteLine("<> DA event raised.");
+
+ var workItemId = Environment.ExpandEnvironmentVariables("%DAS_WORKITEM_ID%");
+
+ Console.WriteLine($"<> WorkItemId is '{workItemId}'");
+
+ var workItemFileName = $"{workItemId}_job.das";
+ var workItemExists = File.Exists(workItemFileName);
+ Console.WriteLine($"Looking for WorkItem file at '{workItemFileName}', exists: {workItemExists}");
+ if (workItemExists)
+ {
+ var workItemContent = File.ReadAllText(workItemFileName);
+
+ var token = ExtractTokenFromWorkItem(workItemContent);
+ if (!string.IsNullOrEmpty(token))
+ {
+ Console.WriteLine($"<> Extracted token from workItem content.");
+ }
+ }
+
+ // Local Change
+ //WorkItemFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
+
+ var dynTempDir = Path.Combine(WorkItemFolder, "dyn_tmp");
+ var app = e.DesignAutomationData?.RevitApp;
+ Console.WriteLine("<> Preparing Dynamo model. Vers 1");
+
+ SetupDARequest? setupReq = null;
+ var setupReqPath = Path.Combine(WorkItemFolder, "setup.json");
+ if (File.Exists(setupReqPath))
+ {
+ try
+ {
+ var setupRequest = File.ReadAllText(setupReqPath);
+ Console.WriteLine(setupRequest);
+
+ setupReq = JsonConvert.DeserializeObject(setupRequest, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.Auto });
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ }
+ }
+
+ Document? doc = null;
+ var cModel = setupReq?.OpenCloudModelLocation;
+ if (cModel != null)
+ {
+ try
+ {
+ Console.WriteLine($"Opening cloud model with Region: {cModel.Region}, Project: {cModel.ProjectGuid}, Model: {cModel.ModelGuid}");
+
+ var cloudModelPath = ModelPathUtils.ConvertCloudGUIDsToCloudPath(cModel.Region, cModel.ProjectGuid, cModel.ModelGuid);
+ Console.WriteLine(doc == null ? $"Cloud model path is {JsonConvert.SerializeObject(cloudModelPath)}" : "doc is not null before opening cloud model");
+ doc = app?.OpenDocumentFile(cloudModelPath, new OpenOptions());
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ }
+ }
+ else if (setupReq?.LocalModelFileName != null)
+ {
+ try
+ {
+ var localModelPath = Path.Combine(WorkItemFolder, setupReq.LocalModelFileName);
+ Console.WriteLine($"Opening local model at {localModelPath}");
+ doc = app?.OpenDocumentFile(localModelPath);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ }
+ }
+ else
+ {
+ doc = e.DesignAutomationData?.RevitDoc;
+ }
+
+ // Startup a new project, maybe an option we can have ?
+ //app.NewProjectDocument(Autodesk.Revit.DB.UnitSystem.Metric);
+
+ if (doc == null) throw new InvalidOperationException("Could not open revit document.");
+
+ var hostloc = typeof(Autodesk.Revit.ApplicationServices.Application).Assembly.Location;
+ var asmLocation = Path.GetDirectoryName(hostloc);
+ Console.WriteLine($"using asm at location {asmLocation}");
+ Console.WriteLine($"Is Loaded {LoadMessage}");
+
+ // need this for cloud, does not work on local
+ var userDataFolder = Path.Combine(dynTempDir, "Dynamo Revit");
+ var commonDataFolder = Path.Combine(dynTempDir, "Dynamo");
+
+ DocumentManager.Instance.PrepareForDesignAutomation(app);
+
+ // Local Change
+ //var geometryFactoryPath = @"C:\\Program Files\\Autodesk\\Revit 2026";
+
+ var loadedLibGVersion = ASMPrealoaderUtils.PreloadAsmFromRevit(controlledApplication.SharedComponentsLocation, DynamoPath);
+ var geometryFactoryPath = ASMPrealoaderUtils.GetGeometryFactoryPath(DynamoPath, loadedLibGVersion);
+
+ PreInstallPythonDependencies();
+
+ model = Dynamo.Applications.Models.RevitDynamoModel.Start(
+ new DefaultStartConfiguration
+ {
+ DynamoCorePath = DynamoPath,
+ DynamoHostPath = DynamoRevitPath,
+ GeometryFactoryPath = geometryFactoryPath,
+ PathResolver = new RevitPathResolver(userDataFolder, commonDataFolder),
+ Context = GetRevitContext(app),
+ AuthProvider = new RevitOAuth2Provider(SynchronizationContext.Current ?? new SynchronizationContext()),
+ ProcessMode = TaskProcessMode.Synchronous,
+ CLIMode = true,
+ IsHeadless = true,
+ IsServiceMode = true
+ });
+
+ LoadMessage = model != null ? "loaded" : "no loaded";
+
+ SetupProfilingHandlers(model);
+
+ var playerHost = new PlayerHostDynamoDefault(model, new DynamoPlayerLogger(logConfig));
+ var workflows = new DynamoModelWorkflows(
+ playerHost,
+ new DynamoPlayerLogger(logConfig));
+
+ var controller = new DynamoControllerImplementation(playerHost, workflows,
+ new DynamoPlayerLogger(logConfig));
+
+ DynamoPlayerLogger.Initialize(playerHost);
+
+ workflows.LoadDependencies(new GraphTarget() { DependenciesPath = WorkItemFolder });
+
+ var dynHandler = new Handler(playerHost, [new DARunGraphController(controller, model, WorkItemFolder)]);
+
+ var runContent = File.ReadAllText(Path.Combine(WorkItemFolder, "run.json"));
+ var testFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
+
+ var output = string.Empty;
+ try
+ {
+ var res = dynHandler.HandleRoute("POST", "/v1/graph/run", runContent);
+ output = res.Result;
+
+ // Force transaction close for now.
+ // This is already called on RevitDynamoModel.OnEvaluationCompleted.
+ // TODO: figure out if this is required here (I noticed, a couple of times, saving the rvt failed after running a graph)
+ // ex. Operation is not permitted when there is any open sub-transaction, transaction, or transaction group.
+ // DYN-10310
+ RevitServices.Transactions.TransactionManager.Instance?.ForceCloseTransaction();
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ }
+
+ Console.WriteLine(output);
+ File.WriteAllText(Path.Combine(WorkItemFolder, "result.json"), output);
+
+ // Default, save the rvt
+ bool saveRvt = setupReq?.GenerateOutputModel ?? true;
+ Console.WriteLine($"{nameof(saveRvt)} is set to {saveRvt}");
+ if (saveRvt)
+ {
+ try
+ {
+ if (doc.IsModelInCloud)
+ {
+ Console.WriteLine("Document is in cloud.");
+ if (doc.IsWorkshared) // work-shared/C4R model
+ {
+ Console.WriteLine("Document is C4R.");
+ // Syncronize with central
+ SynchronizeWithCentralOptions swc = new SynchronizeWithCentralOptions();
+ swc.SetRelinquishOptions(new RelinquishOptions(/*relinquishAll*/true));// Should this be configurable?
+ doc.SynchronizeWithCentral(new TransactWithCentralOptions(), swc);
+ }
+ else
+ {// Single user cloud model
+ Console.WriteLine("Document is single-user cloud model.");
+
+ // Save the project locally (this will detach the model from the cloud, but we will re-upload at a new location)
+ doc.SaveAs(Path.Combine(WorkItemFolder, setupReq.LocalModelFileName));
+
+ /* TODO: figure out if we need to make this work and how.
+
+ doc.SaveCloudModel();
+
+ Console.WriteLine($"uploading with token {token}");
+ // TODO: For single-user cloud models, we need to publish the model after saving so that the changes are reflected in the cloud.
+ var cmPath = doc.GetCloudModelPath();
+ var dmClient = new DataManagementClient(null, new StaticAuthenticationProvider(token));
+ var projId = "b." + setupReq.SaveCloudModelLocation.AccountId;
+
+ var publishTask = dmClient.ExecutePublishModelAsync(projId, new PublishModelPayload()
+ {
+ Type = TypeCommands.Commands,
+ Attributes = new PublishModelPayloadAttributes()
+ {
+ Extension = new PublishModelPayloadAttributesExtension()
+ {
+ Type = TypeCommandtypePublishmodel.CommandsautodeskBim360C4RModelPublish,
+ VarVersion = "1.0.0"
+ }
+ },
+ Relationships = new PublishModelPayloadRelationships()
+ {
+ Resources = new PublishModelPayloadRelationshipsResources()
+ {
+ Data = new List
+ {
+ new PublishModelPayloadRelationshipsResourcesData()
+ {
+ Id = cmPath.GetModelGUID().ToString(),
+ Type = TypeItem.Items
+ }
+ }
+ }
+ }
+ });
+
+ publishTask.Wait();
+ PublishModel respo = publishTask.Result;
+ Console.WriteLine($"Publish result: {JsonConvert.SerializeObject(respo)}");
+ */
+ }
+ }
+ else
+ {
+ /* TODO: Figure ou tif this is useful.
+ var newLoc = setupReq?.SaveCloudModelLocation;
+ if (newLoc != null)
+ {
+ Console.WriteLine($"Saving to new cloud model location with AccountId: {newLoc.AccountId}, ProjectId: {newLoc.ProjectId}, FolderId: {newLoc.FolderId}, ModelName: {newLoc.ModelName}");
+ doc.SaveAsCloudModel(newLoc.AccountId, newLoc.ProjectId, newLoc.FolderId, newLoc.ModelName ?? Path.GetFileName(doc.PathName));
+ }*/
+
+ // Save locally
+ doc.SaveAs(setupReq.LocalModelFileName);
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ }
+ }
+
+ e.Succeeded = true;
+ }
+
+ internal void SetupProfilingHandlers(DynamoModel model)
+ {
+ model.WorkspaceOpened += ws =>
+ {
+ if (ws is not HomeWorkspaceModel homeWorkspace) return;
+
+ var nodeHandlers = new Dictionary[]>();
+
+ EventHandler evaluationStartedHandler = (sender, args) =>
+ {
+ homeWorkspace.EngineController.EnableProfiling(true, homeWorkspace, homeWorkspace.Nodes);
+ Console.WriteLine($"{DateTime.UtcNow:u} : Profiling enabled for {homeWorkspace.Name} dynamo workspace");
+ };
+
+ EventHandler evaluationCompletedHandler = (sender, args) =>
+ {
+ if (workspaceHandlers.TryGetValue(homeWorkspace, out var handlers))
+ {
+ CleanupWorkspaceHandlers(homeWorkspace, handlers.evaluationStartedHandler, handlers.evaluationCompletedHandler, handlers.nodeHandlers);
+ }
+ };
+
+ foreach (var node in homeWorkspace.Nodes)
+ {
+ Action beginHandler = nm =>
+ {
+ Console.WriteLine($"{DateTime.UtcNow:u} : Node {nm.Name} started execution.");
+ };
+
+ Action endHandler = nm =>
+ {
+ var outputSummary = DALogger.SerializeNodeOutputs(nm, homeWorkspace.EngineController);
+ if (!string.IsNullOrEmpty(outputSummary))
+ Console.WriteLine($"{DateTime.UtcNow:u} : Node {nm.Name} outputs: {outputSummary}");
+
+ var runtimeStatus = homeWorkspace.EngineController.LiveRunnerRuntimeCore.RuntimeStatus;
+ var nodeMessages = DALogger.GetNodeMessages(runtimeStatus, nm.GUID);
+ if (!string.IsNullOrEmpty(nodeMessages))
+ Console.WriteLine($"{DateTime.UtcNow:u} : Node {nm.Name} messages: {nodeMessages}");
+
+ Console.WriteLine($"{DateTime.UtcNow:u} : Node {nm.Name} finished execution.");
+ };
+
+ node.NodeExecutionBegin += beginHandler;
+ node.NodeExecutionEnd += endHandler;
+
+ nodeHandlers[node] = [beginHandler, endHandler];
+ }
+
+ homeWorkspace.EvaluationStarted += evaluationStartedHandler;
+ homeWorkspace.EvaluationCompleted += evaluationCompletedHandler;
+
+ workspaceHandlers[homeWorkspace] = (evaluationStartedHandler, evaluationCompletedHandler, nodeHandlers);
+ };
+ }
+
+ private void CleanupWorkspaceHandlers(
+ HomeWorkspaceModel workspace,
+ EventHandler? evaluationStartedHandler,
+ EventHandler? evaluationCompletedHandler,
+ Dictionary[]> nodeHandlers)
+ {
+ if (evaluationStartedHandler != null)
+ workspace.EvaluationStarted -= evaluationStartedHandler;
+
+ if (evaluationCompletedHandler != null)
+ workspace.EvaluationCompleted -= evaluationCompletedHandler;
+
+ foreach (var kvp in nodeHandlers)
+ {
+ var node = kvp.Key;
+ var nodeHandlerArray = kvp.Value;
+
+ if (nodeHandlerArray.Length >= 2)
+ {
+ node.NodeExecutionBegin -= nodeHandlerArray[0];
+ node.NodeExecutionEnd -= nodeHandlerArray[1];
+ }
+ }
+
+ workspaceHandlers.Remove(workspace);
+ }
+
+ private void PreInstallPythonDependencies()
+ {
+ try
+ {
+ // Preload all python assemblies at the PythonDllFolder.
+ foreach (var pyDll in Directory.EnumerateFiles(Path.Combine(WorkItemFolder, PythonDllFolder), "*.dll"))
+ {
+ Assembly.LoadFrom(pyDll);
+ }
+
+ var pyIncluded = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(x => x.GetName().Name == "Python.Included");
+ if (pyIncluded == null)
+ {
+ throw new Exception("Could not find Python.Included assembly");
+ }
+ var type = pyIncluded.GetType("Python.Included.Installer");
+ if (type == null)
+ {
+ throw new Exception("null Installer type");
+ }
+ var property = type.GetProperty("INSTALL_PATH", BindingFlags.Public | BindingFlags.Static);
+ if (property == null)
+ {
+ throw new Exception("null INSTALL_PATH property");
+ }
+
+ // Set the python install location to the DA workfolder (that is the only place we have wrie access)
+ property.SetValue(null, WorkItemFolder);
+
+ // Dynamo's 'VerifyEngineReferences' wants all the PythonEngine's dependencies to be in the Dynamo folder.
+ // Temporary until we fix it on the Dynamo side.
+ if (PythonEngineManager.Instance.AvailableEngines.Count == 0)
+ {
+ PropertyInfo instanceProp = typeof(CPythonEvaluator).GetProperty("Instance", BindingFlags.NonPublic | BindingFlags.Static);
+ if (instanceProp != null)
+ {
+ PythonEngine engine = (PythonEngine)instanceProp.GetValue(null);
+ if (engine == null)
+ {
+ throw new Exception($"Could not get a valid PythonEngine instance");
+ }
+
+ PythonEngineManager.Instance.AvailableEngines.Add(engine);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("Could not setup python " + ex.Message);
+ }
+ }
+ }
+}
diff --git a/src/DADynamoApp/DALogger.cs b/src/DADynamoApp/DALogger.cs
new file mode 100644
index 0000000000..7c901150b1
--- /dev/null
+++ b/src/DADynamoApp/DALogger.cs
@@ -0,0 +1,149 @@
+using Dynamo.Graph.Nodes;
+using ProtoCore;
+using System.Reflection;
+using System.Text.Json;
+
+[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("RevitSystemTests")]
+
+namespace DADynamoApp;
+
+///
+/// Utility helpers for DynamoRevit Design Automation profiling output.
+/// All Dynamo internal logging is already redirected to stdout by IsServiceMode=true.
+/// This class provides node output serialization via reflection into DynamoPlayer.
+///
+internal static class DALogger
+{
+ // Cached reflection members for Player's WatchNodeHandler methods
+ private static MethodInfo? getNodeValueMethod;
+ private static MethodInfo? processWatchTreeMethod;
+
+ private static readonly JsonSerializerOptions jsonOptions = new JsonSerializerOptions
+ {
+ WriteIndented = true,
+ DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingDefault
+ };
+
+ ///
+ /// Serializes node output values by getting data from the runtime mirror
+ /// and using Player's serialization logic via reflection.
+ ///
+ public static string SerializeNodeOutputs(NodeModel node, Dynamo.Engine.EngineController engineController, int maxLength = 2000)
+ {
+ try
+ {
+ var variableName = node.AstIdentifierForPreview.Value;
+ if (string.IsNullOrEmpty(variableName)) return string.Empty;
+
+ var runtimeMirror = engineController.GetMirror(variableName);
+ if (runtimeMirror == null) return string.Empty;
+
+ var mirrorData = runtimeMirror.GetData();
+ if (mirrorData == null) return string.Empty;
+
+ var valueContainer = GetNodeValueStringFromMirrorData(mirrorData);
+ if (valueContainer == null) return string.Empty;
+
+ var valueString = JsonSerializer.Serialize(valueContainer, jsonOptions);
+ if (string.IsNullOrEmpty(valueString)) return string.Empty;
+
+ if (valueString.Length > maxLength)
+ valueString = valueString.Substring(0, maxLength) + $"... (truncated from {valueString.Length} chars)";
+
+ return valueString;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"Error serializing node outputs: {ex}");
+ return string.Empty;
+ }
+ }
+
+ private static object? GetNodeValueStringFromMirrorData(object mirrorData)
+ {
+ try
+ {
+ var obj = GetNodeValueViaReflection(mirrorData);
+ if (obj == null) return null;
+
+ if (obj is System.Collections.IList list && list.Count == 0)
+ return new { Value = "Empty List" };
+
+ if (obj is System.Collections.IDictionary dict && dict.Count == 0)
+ return new { Value = "Empty Dictionary" };
+
+ return ProcessWatchTreeViaReflection(obj);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"Error in GetNodeValueStringFromMirrorData: {ex}");
+ return null;
+ }
+ }
+
+ private static object? GetNodeValueViaReflection(object mirrorData)
+ {
+ if (getNodeValueMethod == null)
+ {
+ var assembly = AppDomain.CurrentDomain.GetAssemblies()
+ .FirstOrDefault(a => a.GetName().Name == "DynamoPlayer.Workflows")
+ ?? throw new InvalidOperationException("DynamoPlayer.Workflows assembly not found");
+
+ var type = assembly.GetType("DynamoPlayer.WatchNodeHandler")
+ ?? throw new InvalidOperationException("WatchNodeHandler type not found");
+
+ getNodeValueMethod = type.GetMethod("GetNodeValue", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static)
+ ?? throw new InvalidOperationException("GetNodeValue method not found");
+ }
+
+ try
+ {
+ return getNodeValueMethod.Invoke(null, [mirrorData]);
+ }
+ catch (TargetInvocationException ex)
+ {
+ throw new InvalidOperationException($"GetNodeValue invocation failed: {ex.InnerException?.Message}", ex.InnerException);
+ }
+ }
+
+ private static object? ProcessWatchTreeViaReflection(object obj)
+ {
+ if (processWatchTreeMethod == null)
+ {
+ var assembly = AppDomain.CurrentDomain.GetAssemblies()
+ .FirstOrDefault(a => a.GetName().Name == "DynamoPlayer.Workflows")
+ ?? throw new InvalidOperationException("DynamoPlayer.Workflows assembly not found");
+
+ var type = assembly.GetType("DynamoPlayer.WatchNodeHandler")
+ ?? throw new InvalidOperationException("WatchNodeHandler type not found");
+
+ processWatchTreeMethod = type.GetMethod("ProcessWatchTree", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static)
+ ?? throw new InvalidOperationException("ProcessWatchTree method not found");
+ }
+
+ try
+ {
+ return processWatchTreeMethod.Invoke(null, [obj, null]);
+ }
+ catch (TargetInvocationException ex)
+ {
+ throw new InvalidOperationException($"ProcessWatchTree invocation failed: {ex.InnerException?.Message}", ex.InnerException);
+ }
+ }
+
+ ///
+ /// Gets runtime warnings for a specific node as a JSON string.
+ ///
+ public static string GetNodeMessages(RuntimeStatus runtimeStatus, Guid nodeId)
+ {
+ var warnings = new List();
+
+ foreach (var warning in runtimeStatus.Warnings)
+ {
+ if (warning.GraphNodeGuid == nodeId)
+ warnings.Add(warning.Message);
+ }
+
+ return JsonSerializer.Serialize(new { warnings = warnings.Count > 0 ? warnings : null }, jsonOptions);
+ }
+}
diff --git a/src/DADynamoApp/DARunGraphController.cs b/src/DADynamoApp/DARunGraphController.cs
new file mode 100644
index 0000000000..e061599b44
--- /dev/null
+++ b/src/DADynamoApp/DARunGraphController.cs
@@ -0,0 +1,33 @@
+using Dynamo.Models;
+using DynamoPlayer;
+
+namespace DADynamoApp
+{
+ internal class DARunGraphController : DynamoController
+ {
+ IDynamoController implementation;
+ string workFolder = string.Empty;
+ DynamoModel model;
+
+ public DARunGraphController(IDynamoController implementation, DynamoModel model, string workFolder) : base(implementation)
+ {
+ this.workFolder = workFolder;
+ this.implementation = implementation;
+ this.model = model;
+ }
+
+ [Route("graph/run", Name = "post-graph-run")]
+ public new Task PostGraphRun([FromBody] RunGraph body)
+ {
+ if (body.Target is CurrentGraphTarget)
+ {
+ this.model.OpenFileFromPath(Path.Combine(workFolder, "run.dyn"));
+ }
+ else if (body.Target is PathGraphTarget pGraphTarget)
+ {
+ pGraphTarget.Path = Path.Combine(this.workFolder, pGraphTarget.Path);
+ }
+ return implementation.PostGraphRunAsync(body);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/DADynamoApp/SetupDARequest.cs b/src/DADynamoApp/SetupDARequest.cs
new file mode 100644
index 0000000000..ab16a6a8f7
--- /dev/null
+++ b/src/DADynamoApp/SetupDARequest.cs
@@ -0,0 +1,72 @@
+using Newtonsoft.Json;
+
+namespace DADynamoApp
+{
+ ///
+ /// Configuration details for a cloud model.
+ ///
+ internal class OpenCloudModelLocation
+ {
+ ///
+ /// Represents the region where the cloud model is hosted.
+ ///
+ public string Region;
+
+ ///
+ /// Represents the unique identifier for a project.
+ ///
+ public Guid ProjectGuid;
+
+ ///
+ /// Represents the unique identifier for the model.
+ ///
+ public Guid ModelGuid;
+ }
+
+ ///
+ /// Represents the save location for the current DA work model.
+ ///
+ internal class SaveCloudModelLocation
+ {
+ ///
+ /// Gets or sets the unique identifier for the account.
+ ///
+ public Guid AccountId { get; set; }
+
+ ///
+ /// Gets or sets the unique identifier for the project.
+ ///
+ public Guid ProjectId { get; set; }
+
+ ///
+ /// Gets or sets the unique identifier for the folder.
+ ///
+ public string FolderId { get; set; }
+
+ ///
+ /// Gets or sets the name of the model to be created on the save operation.
+ ///
+ public string ModelName { get; set; } = string.Empty;
+ }
+
+ ///
+ /// Request body used to setup aspects of the Design Automation environment.
+ ///
+ internal class SetupDARequest
+ {
+ //
+ // Summary:
+ // Save the revit document to the default result.rvt file.
+ [JsonProperty(nameof(GenerateOutputModel), Required = Required.DisallowNull, NullValueHandling = NullValueHandling.Ignore)]
+ public bool GenerateOutputModel { get; set; } = false;
+
+ ///
+ /// Gets or sets the name of the Revit model file.
+ ///
+ public string LocalModelFileName { get; set; } = string.Empty;
+
+ public OpenCloudModelLocation? OpenCloudModelLocation { get; set; } = null;
+
+ public SaveCloudModelLocation? SaveCloudModelLocation { get; set; } = null;
+ }
+}
diff --git a/src/DynamoRevit.All.sln b/src/DynamoRevit.All.sln
index 821dcd9a22..4237e0644a 100644
--- a/src/DynamoRevit.All.sln
+++ b/src/DynamoRevit.All.sln
@@ -50,6 +50,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssemblyInfoGenerator", "As
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RevitSystemTests", "..\test\Libraries\RevitIntegrationTests\RevitSystemTests.csproj", "{9ADADC68-36A3-4A21-9B54-298154A88720}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DADynamoApp", "DADynamoApp\DADynamoApp.csproj", "{B3F7C2D1-4E8A-4B6C-A9D2-6F1E8C3B7A05}"
+EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4466E6F6-F644-43AB-96B3-5ECE1622E711}"
ProjectSection(SolutionItems) = preProject
..\.version = ..\.version
@@ -61,6 +63,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DynamoRevitIcons", "DynamoRevitIcons\DynamoRevitIcons.csproj", "{A31E274C-524A-40CA-85FF-595D3DB53777}"
ProjectSection(ProjectDependencies) = postProject
+ {92A46535-D870-4E1A-AED0-7492789E9C4A} = {92A46535-D870-4E1A-AED0-7492789E9C4A}
{133FC760-5699-46D9-BEA6-E816B5F01016} = {133FC760-5699-46D9-BEA6-E816B5F01016}
EndProjectSection
EndProject
@@ -190,6 +193,14 @@ Global
{9ADADC68-36A3-4A21-9B54-298154A88720}.Release|NET100.Build.0 = Release|NET100
{9ADADC68-36A3-4A21-9B54-298154A88720}.Release|NET80.ActiveCfg = Release|NET80
{9ADADC68-36A3-4A21-9B54-298154A88720}.Release|NET80.Build.0 = Release|NET80
+ {B3F7C2D1-4E8A-4B6C-A9D2-6F1E8C3B7A05}.Debug|NET100.ActiveCfg = Debug|NET10_DA
+ {B3F7C2D1-4E8A-4B6C-A9D2-6F1E8C3B7A05}.Debug|NET100.Build.0 = Debug|NET10_DA
+ {B3F7C2D1-4E8A-4B6C-A9D2-6F1E8C3B7A05}.Debug|NET80.ActiveCfg = Debug|NET10_DA
+ {B3F7C2D1-4E8A-4B6C-A9D2-6F1E8C3B7A05}.Debug|NET80.Build.0 = Debug|NET10_DA
+ {B3F7C2D1-4E8A-4B6C-A9D2-6F1E8C3B7A05}.Release|NET100.ActiveCfg = Release|NET10_DA
+ {B3F7C2D1-4E8A-4B6C-A9D2-6F1E8C3B7A05}.Release|NET100.Build.0 = Release|NET10_DA
+ {B3F7C2D1-4E8A-4B6C-A9D2-6F1E8C3B7A05}.Release|NET80.ActiveCfg = Release|NET10_DA
+ {B3F7C2D1-4E8A-4B6C-A9D2-6F1E8C3B7A05}.Release|NET80.Build.0 = Release|NET10_DA
{A31E274C-524A-40CA-85FF-595D3DB53777}.Debug|NET100.ActiveCfg = Debug|NET100
{A31E274C-524A-40CA-85FF-595D3DB53777}.Debug|NET100.Build.0 = Debug|NET100
{A31E274C-524A-40CA-85FF-595D3DB53777}.Debug|NET80.ActiveCfg = Debug|NET80
diff --git a/src/DynamoRevit.DA.sln b/src/DynamoRevit.DA.sln
new file mode 100644
index 0000000000..a6c778b0fc
--- /dev/null
+++ b/src/DynamoRevit.DA.sln
@@ -0,0 +1,99 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.1.32328.378
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{FA7BE306-A3B0-45FA-9D87-0C69E6932C13}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RevitNodes", "Libraries\RevitNodes\RevitNodes.csproj", "{0BC2A611-BD0E-4FCC-A1DE-81F14ED369B2}"
+ ProjectSection(ProjectDependencies) = postProject
+ {133FC760-5699-46D9-BEA6-E816B5F01016} = {133FC760-5699-46D9-BEA6-E816B5F01016}
+ EndProjectSection
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RevitNodesUI", "Libraries\RevitNodesUI\RevitNodesUI.csproj", "{75940ACC-3708-4526-8D91-7E3365BAF682}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RevitServices", "Libraries\RevitServices\RevitServices.csproj", "{E4701F9E-41AB-4044-8166-85D924FEB632}"
+ ProjectSection(ProjectDependencies) = postProject
+ {133FC760-5699-46D9-BEA6-E816B5F01016} = {133FC760-5699-46D9-BEA6-E816B5F01016}
+ EndProjectSection
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Migrations", "Libraries\Migrations\Migrations.csproj", "{06B9E5B0-7C50-4351-9D88-E159DC25755F}"
+ ProjectSection(ProjectDependencies) = postProject
+ {133FC760-5699-46D9-BEA6-E816B5F01016} = {133FC760-5699-46D9-BEA6-E816B5F01016}
+ EndProjectSection
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssemblyInfoGenerator", "AssemblySharedInfoGenerator\AssemblyInfoGenerator.csproj", "{133FC760-5699-46D9-BEA6-E816B5F01016}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4466E6F6-F644-43AB-96B3-5ECE1622E711}"
+ ProjectSection(SolutionItems) = preProject
+ ..\.version = ..\.version
+ ..\CHANGELOG.md = ..\CHANGELOG.md
+ ..\README.md = ..\README.md
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "config", "config", "{9568462D-249F-4494-856B-5B25751DB361}"
+ ProjectSection(SolutionItems) = preProject
+ Config.xml = Config.xml
+ Config\CS_SDK.props = Config\CS_SDK.props
+ Config\dynamo-nuget.config = Config\dynamo-nuget.config
+ Config\packages-template.aget = Config\packages-template.aget
+ Config\packages.aget = Config\packages.aget
+ Config\user_local.props = Config\user_local.props
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DADynamoApp", "DADynamoApp\DADynamoApp.csproj", "{66A0E1C8-2514-48B7-8406-536983F57F88}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DynamoRevit", "DynamoRevit\DynamoRevit.csproj", "{BD7126B6-E716-4024-854F-6DA2CFA25B84}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|NET10_DA = Debug|NET10_DA
+ Release|NET10_DA = Release|NET10_DA
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {0BC2A611-BD0E-4FCC-A1DE-81F14ED369B2}.Debug|NET10_DA.ActiveCfg = Debug|NET10_DA
+ {0BC2A611-BD0E-4FCC-A1DE-81F14ED369B2}.Debug|NET10_DA.Build.0 = Debug|NET10_DA
+ {0BC2A611-BD0E-4FCC-A1DE-81F14ED369B2}.Release|NET10_DA.ActiveCfg = Release|NET10_DA
+ {0BC2A611-BD0E-4FCC-A1DE-81F14ED369B2}.Release|NET10_DA.Build.0 = Release|NET10_DA
+ {75940ACC-3708-4526-8D91-7E3365BAF682}.Debug|NET10_DA.ActiveCfg = Debug|NET10_DA
+ {75940ACC-3708-4526-8D91-7E3365BAF682}.Debug|NET10_DA.Build.0 = Debug|NET10_DA
+ {75940ACC-3708-4526-8D91-7E3365BAF682}.Release|NET10_DA.ActiveCfg = Release|NET10_DA
+ {75940ACC-3708-4526-8D91-7E3365BAF682}.Release|NET10_DA.Build.0 = Release|NET10_DA
+ {E4701F9E-41AB-4044-8166-85D924FEB632}.Debug|NET10_DA.ActiveCfg = Debug|NET10_DA
+ {E4701F9E-41AB-4044-8166-85D924FEB632}.Debug|NET10_DA.Build.0 = Debug|NET10_DA
+ {E4701F9E-41AB-4044-8166-85D924FEB632}.Release|NET10_DA.ActiveCfg = Release|NET10_DA
+ {E4701F9E-41AB-4044-8166-85D924FEB632}.Release|NET10_DA.Build.0 = Release|NET10_DA
+ {06B9E5B0-7C50-4351-9D88-E159DC25755F}.Debug|NET10_DA.ActiveCfg = Debug|NET10_DA
+ {06B9E5B0-7C50-4351-9D88-E159DC25755F}.Debug|NET10_DA.Build.0 = Debug|NET10_DA
+ {06B9E5B0-7C50-4351-9D88-E159DC25755F}.Release|NET10_DA.ActiveCfg = Release|NET10_DA
+ {06B9E5B0-7C50-4351-9D88-E159DC25755F}.Release|NET10_DA.Build.0 = Release|NET10_DA
+ {133FC760-5699-46D9-BEA6-E816B5F01016}.Debug|NET10_DA.ActiveCfg = Debug|NET10_DA
+ {133FC760-5699-46D9-BEA6-E816B5F01016}.Debug|NET10_DA.Build.0 = Debug|NET10_DA
+ {133FC760-5699-46D9-BEA6-E816B5F01016}.Release|NET10_DA.ActiveCfg = Release|NET10_DA
+ {133FC760-5699-46D9-BEA6-E816B5F01016}.Release|NET10_DA.Build.0 = Release|NET10_DA
+ {66A0E1C8-2514-48B7-8406-536983F57F88}.Debug|NET10_DA.ActiveCfg = Debug|NET10_DA
+ {66A0E1C8-2514-48B7-8406-536983F57F88}.Debug|NET10_DA.Build.0 = Debug|NET10_DA
+ {66A0E1C8-2514-48B7-8406-536983F57F88}.Release|NET10_DA.ActiveCfg = Release|NET10_DA
+ {66A0E1C8-2514-48B7-8406-536983F57F88}.Release|NET10_DA.Build.0 = Release|NET10_DA
+ {BD7126B6-E716-4024-854F-6DA2CFA25B84}.Debug|NET10_DA.ActiveCfg = Debug|NET10_DA
+ {BD7126B6-E716-4024-854F-6DA2CFA25B84}.Debug|NET10_DA.Build.0 = Debug|NET10_DA
+ {BD7126B6-E716-4024-854F-6DA2CFA25B84}.Release|NET10_DA.ActiveCfg = Release|NET10_DA
+ {BD7126B6-E716-4024-854F-6DA2CFA25B84}.Release|NET10_DA.Build.0 = Release|NET10_DA
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {0BC2A611-BD0E-4FCC-A1DE-81F14ED369B2} = {FA7BE306-A3B0-45FA-9D87-0C69E6932C13}
+ {75940ACC-3708-4526-8D91-7E3365BAF682} = {FA7BE306-A3B0-45FA-9D87-0C69E6932C13}
+ {E4701F9E-41AB-4044-8166-85D924FEB632} = {FA7BE306-A3B0-45FA-9D87-0C69E6932C13}
+ {06B9E5B0-7C50-4351-9D88-E159DC25755F} = {FA7BE306-A3B0-45FA-9D87-0C69E6932C13}
+ {9568462D-249F-4494-856B-5B25751DB361} = {4466E6F6-F644-43AB-96B3-5ECE1622E711}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {757AAA40-191F-4673-9B04-8270A3370BCA}
+ EndGlobalSection
+ GlobalSection(SharedMSBuildProjectFiles) = preSolution
+ SharedUtilities\SharedUtilities.projitems*{66a0e1c8-2514-48b7-8406-536983f57f88}*SharedItemsImports = 5
+ SharedUtilities\SharedUtilities.projitems*{bd7126b6-e716-4024-854f-6da2cfa25b84}*SharedItemsImports = 5
+ EndGlobalSection
+EndGlobal
diff --git a/src/DynamoRevit/DynamoRevit.cs b/src/DynamoRevit/DynamoRevit.cs
index f2a9b7b5dc..66d603ae95 100644
--- a/src/DynamoRevit/DynamoRevit.cs
+++ b/src/DynamoRevit/DynamoRevit.cs
@@ -524,34 +524,6 @@ private static void UpdateSystemPathForProcess()
#region Initialization
- ///
- /// DynamoShapeManager.dll is a companion assembly of Dynamo core components,
- /// we do not want a static reference to it (since the Revit add-on can be
- /// installed anywhere that's outside of Dynamo), we do not want a duplicated
- /// reference to it. Here we use reflection to obtain GetGeometryFactoryPath
- /// method, and call it to get the geometry factory assembly path.
- ///
- /// The path where DynamoShapeManager.dll can be
- /// located.
- /// The version of DynamoShapeManager.dll
- /// Returns the full path to geometry factory assembly.
- ///
- public static string GetGeometryFactoryPath(string corePath, Version version)
- {
- var dynamoAsmPath = Path.Combine(corePath, "DynamoShapeManager.dll");
- var assembly = Assembly.LoadFrom(dynamoAsmPath);
- if (assembly == null)
- throw new FileNotFoundException("File not found", dynamoAsmPath);
-
- var utilities = assembly.GetType("DynamoShapeManager.Utilities");
- var getGeometryFactoryPath = utilities.GetMethod("GetGeometryFactoryPath2");
-
- return (getGeometryFactoryPath.Invoke(null,
- new object[] { corePath, version }) as string);
- }
-
-
-
private static void PreloadDynamoCoreDlls()
{
// Assume Revit Install folder as look for root. Assembly name is compromised.
@@ -611,15 +583,16 @@ private static RevitDynamoModel InitializeCoreModel(DynamoRevitCommandData comma
// when Dynamo runs on top of Revit we must load the same version of ASM as revit
// so tell Dynamo core we've loaded that version.
- var loadedLibGVersion = PreloadAsmFromRevit();
+ var asmLocation = DynamoRevitApp.ControlledApplication.SharedComponentsLocation;
+ var loadedLibGVersion = ASMPrealoaderUtils.PreloadAsmFromRevit(asmLocation, DynamoRevitApp.DynamoCorePath);
return RevitDynamoModel.Start(
new RevitDynamoModel.RevitStartConfiguration()
{
DynamoCorePath = corePath,
DynamoHostPath = dynamoRevitRoot,
- GeometryFactoryPath = GetGeometryFactoryPath(corePath, loadedLibGVersion),
+ GeometryFactoryPath = ASMPrealoaderUtils.GetGeometryFactoryPath(corePath, loadedLibGVersion),
PathResolver = new RevitPathResolver(userDataFolder, commonDataFolder),
Context = GetRevitContext(commandData),
SchedulerThread = new RevitSchedulerThread(commandData.Application),
@@ -631,61 +604,6 @@ private static RevitDynamoModel InitializeCoreModel(DynamoRevitCommandData comma
});
}
- internal static Version PreloadAsmFromRevit()
- {
- var asmLocation = DynamoRevitApp.ControlledApplication.SharedComponentsLocation;
-
- Version libGVersion = findRevitASMVersion(asmLocation);
- var dynCorePath = DynamoRevitApp.DynamoCorePath;
- // Get the corresponding libG preloader location for the target ASM loading version.
- // If there is exact match preloader version to the target ASM version, use it,
- // otherwise use the closest below.
- var preloaderLocation = DynamoShapeManager.Utilities.GetLibGPreloaderLocation(libGVersion, dynCorePath);
-
- // [Tech Debt] (Will refactor the code later)
- // The LibG version maybe different in Dynamo and Revit, using the one which is in Dynamo.
- Version preLoadLibGVersion = PreloadLibGVersion(preloaderLocation);
- DynamoShapeManager.Utilities.PreloadAsmFromPath(preloaderLocation, asmLocation);
- return preLoadLibGVersion;
- }
-
- // [Tech Debt] (Will refactor the code later)
- ///
- /// Return the preload version of LibG.
- ///
- ///
- ///
- internal static Version PreloadLibGVersion(string preloaderLocation)
- {
- preloaderLocation = new DirectoryInfo(preloaderLocation).Name;
- var regExp = new Regex(@"^libg_(\d\d\d)_(\d)_(\d)$", RegexOptions.IgnoreCase);
-
- var match = regExp.Match(preloaderLocation);
- if (match.Groups.Count == 4)
- {
- return new Version(
- Convert.ToInt32(match.Groups[1].Value),
- Convert.ToInt32(match.Groups[2].Value),
- Convert.ToInt32(match.Groups[3].Value));
- }
-
- return new Version();
- }
-
- ///
- /// Returns the version of ASM which is installed with Revit at the requested path.
- /// This version number can be used to load the appropriate libG version.
- ///
- /// path where asm dlls are located, this is usually the product(Revit) install path
- ///
- internal static Version findRevitASMVersion(string asmLocation)
- {
- var lookup = new InstalledProductLookUp("Revit", "ASMAHL*.dll");
- var product = lookup.GetProductFromInstallPath(asmLocation);
- var libGversion = new Version(product.VersionInfo.Item1, product.VersionInfo.Item2, product.VersionInfo.Item3);
- return libGversion;
- }
-
private static DynamoViewModel InitializeCoreViewModel(RevitDynamoModel revitDynamoModel)
{
var viewModel = DynamoRevitViewModel.Start(
@@ -1162,116 +1080,4 @@ public static void AddIdleAction(Action a)
}
}
}
-
- ///
- /// Defines parameters used for loading internal Dynamo Revit packages
- ///
- [Serializable()]
- public class InternalPackage
- {
- ///
- /// keeps the path to the node file
- ///
- public string NodePath { get; set; }
-
- ///
- /// keeps the path to the layoutSpecs.json file
- ///
- public string LayoutSpecsPath { get; set; }
-
- ///
- /// keeps paths to additional assembly load paths
- ///
- public List AdditionalAssemblyLoadPaths { get; set; }
- }
- internal static class DynamoRevitInternalNodes
- {
- private const string InternalNodesDir = "nodes";
- private static IEnumerable GetAllInternalPackageFiles()
- {
- string currentAssemblyPath = Assembly.GetExecutingAssembly().Location;
- string currentAssemblyDir = Path.GetDirectoryName(currentAssemblyPath);
-
- string internalNodesDir = Path.Combine(currentAssemblyDir, InternalNodesDir);
- if (false == Directory.Exists(internalNodesDir))
- {
- return new List();
- }
-
- string[] internalNodesFolders = Directory.GetDirectories(internalNodesDir);
-
- List internalPackageFiles = new List();
- foreach (string dir in internalNodesFolders)
- {
- string internalPackageFile = Path.Combine(dir, "internalPackage.xml");
- if (true == File.Exists(internalPackageFile))
- {
- internalPackageFiles.Add(internalPackageFile);
- }
- }
- return internalPackageFiles;
- }
- private static IEnumerable ParseinternalPackageFiles(IEnumerable internalPackageFiles)
- {
- List internalPackages = new List();
- string basePath = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
-
- foreach (string internalPackageFile in internalPackageFiles)
- {
- try
- {
- string internalPackageDir = Path.GetDirectoryName(internalPackageFile);
- using (StreamReader reader = new StreamReader(internalPackageFile))
- {
- XmlSerializer serializer = new XmlSerializer(typeof(InternalPackage));
- InternalPackage intPackage = serializer.Deserialize(reader) as InternalPackage;
-
- // convert to absolute path, if needed
- if (false == Path.IsPathRooted(intPackage.NodePath))
- {
- intPackage.NodePath = Path.Combine(internalPackageDir, intPackage.NodePath);
- }
-
- // convert to absolute path, if needed
- if (false == Path.IsPathRooted(intPackage.LayoutSpecsPath))
- {
- intPackage.LayoutSpecsPath = Path.Combine(internalPackageDir, intPackage.LayoutSpecsPath);
- }
-
- // convert to absolute paths, if needed
- if (null != intPackage.AdditionalAssemblyLoadPaths && intPackage.AdditionalAssemblyLoadPaths.Count > 0)
- {
- intPackage.AdditionalAssemblyLoadPaths = intPackage.AdditionalAssemblyLoadPaths
- .Select(p => !Path.IsPathRooted(p) ? Path.Combine(basePath, p) : p)
- .Where(Path.Exists).ToList();
- }
-
- internalPackages.Add(intPackage);
- }
- }
- catch (Exception)
- {
- Console.WriteLine(string.Format("Exception while trying to parse internalPackage file {0}", internalPackageFile));
- }
- }
-
- return internalPackages;
- }
- internal static IEnumerable GetNodesToPreload()
- {
- IEnumerable internalPackageFiles = GetAllInternalPackageFiles();
- return ParseinternalPackageFiles(internalPackageFiles).Select(pkg => pkg.NodePath);
- }
- internal static IEnumerable GetLayoutSpecsFiles()
- {
- IEnumerable internalPackageFiles = GetAllInternalPackageFiles();
- return ParseinternalPackageFiles(internalPackageFiles).Select(pkg => pkg.LayoutSpecsPath);
- }
-
- internal static IEnumerable GetAdditionalAssemblyLoadPaths()
- {
- IEnumerable internalPackageFiles = GetAllInternalPackageFiles();
- return ParseinternalPackageFiles(internalPackageFiles).SelectMany(pkg => pkg.AdditionalAssemblyLoadPaths);
- }
- }
-}
\ No newline at end of file
+}
diff --git a/src/DynamoRevit/DynamoRevit.csproj b/src/DynamoRevit/DynamoRevit.csproj
index 2a543c362d..29302bf267 100644
--- a/src/DynamoRevit/DynamoRevit.csproj
+++ b/src/DynamoRevit/DynamoRevit.csproj
@@ -10,40 +10,26 @@
true
- prompt
- 3
- full
$(NoWarn);618
- true
- false
MinimumRecommendedRules.ruleset
- false
- $(BuildDependsOn);AfterBuildMigrated
- if exist $(ProjectDir)PostBuildStep.bat call $(ProjectDir)PostBuildStep.bat $(SolutionDir)
- DynamoRevitDS
- true
- true
-
-
- None
-
-
- false
- TRACE;DEBUG
- false
-
-
- true
- TRACE
-
-
- true
-
-
- if exist $(ProjectDir)PostBuildStep.bat call $(ProjectDir)PostBuildStep.bat $(SolutionDir)
- x64
-
+ false
+ $(BuildDependsOn);AfterBuildMigrated
+ if exist $(ProjectDir)PostBuildStep.bat call $(ProjectDir)PostBuildStep.bat $(SolutionDir)
+ DynamoRevitDS
+ true
+ true
+
+
+ None
+
+
+ true
+
+
+ if exist $(ProjectDir)PostBuildStep.bat call $(ProjectDir)PostBuildStep.bat $(SolutionDir)
+ x64
+
@@ -81,6 +67,33 @@
Resources.en-US.Designer.cs
+
+
+ $(PACKAGESPATH)\DynamoVisualProgramming.Core\lib\$(DCoreLibSubFolder)\ProtoCore.dll
+ $(DYNAMOBUILDPATH)\ProtoCore.dll
+ False
+
+
+ $(PACKAGESPATH)\DynamoVisualProgramming.Core\lib\$(DCoreLibSubFolder)\DynamoCore.dll
+ $(DYNAMOBUILDPATH)\DynamoCore.dll
+ False
+
+
+ $(PACKAGESPATH)\DynamoVisualProgramming.Core\lib\$(DCoreLibSubFolder)\DynamoUtilities.dll
+ $(DYNAMOBUILDPATH)\DynamoUtilities.dll
+ False
+
+
+ $(PACKAGESPATH)\DynamoVisualProgramming.Core\lib\$(DCoreLibSubFolder)\DynamoShapeManager.dll
+ $(DYNAMOBUILDPATH)\DynamoShapeManager.dll
+ False
+
+
+ $(PACKAGESPATH)\DynamoVisualProgramming.Core\lib\$(DCoreLibSubFolder)\DynamoInstallDetective.dll
+ $(DYNAMOBUILDPATH)\DynamoInstallDetective.dll
+ False
+
+
@@ -98,6 +111,11 @@
+
+
+
+
+
@@ -107,7 +125,7 @@
-
-
+
+
\ No newline at end of file
diff --git a/src/DynamoRevit/DynamoRevitApp.cs b/src/DynamoRevit/DynamoRevitApp.cs
index e6a7b58f39..46d5c0cc0c 100644
--- a/src/DynamoRevit/DynamoRevitApp.cs
+++ b/src/DynamoRevit/DynamoRevitApp.cs
@@ -26,8 +26,6 @@
namespace Dynamo.Applications
{
-
-
[Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual),
Regeneration(RegenerationOption.Manual)]
public class DynamoRevitApp : IExternalApplication
@@ -95,7 +93,6 @@ private static string GetDynamoRoot(string dynamoRevitRoot)
private static string dynamopath;
private static readonly Queue idleActionQueue = new Queue(10);
- private static EventHandlerProxy proxy;
private AddInCommandBinding dynamoCommand;
private Result loadDependentComponents()
@@ -253,9 +250,10 @@ public static void AddIdleAction(Action a)
}
}
+ [Obsolete("This property will be made internal")]
public static EventHandlerProxy EventHandlerProxy
{
- get { return proxy; }
+ get { return EventHandlerProxy.Instance; }
}
// should be handled by the ModelUpdater class. But there are some
@@ -286,28 +284,26 @@ private void SubscribeApplicationEvents()
{
UIControlledApplication.Idling += OnApplicationIdle;
- proxy = new EventHandlerProxy();
-
- UIControlledApplication.ViewActivated += proxy.OnApplicationViewActivated;
- UIControlledApplication.ViewActivating += proxy.OnApplicationViewActivating;
+ UIControlledApplication.ViewActivated += EventHandlerProxy.Instance.OnApplicationViewActivated;
+ UIControlledApplication.ViewActivating += EventHandlerProxy.Instance.OnApplicationViewActivating;
- ControlledApplication.DocumentClosing += proxy.OnApplicationDocumentClosing;
- ControlledApplication.DocumentClosed += proxy.OnApplicationDocumentClosed;
- ControlledApplication.DocumentOpened += proxy.OnApplicationDocumentOpened;
+ ControlledApplication.DocumentClosing += EventHandlerProxy.Instance.OnApplicationDocumentClosing;
+ ControlledApplication.DocumentClosed += EventHandlerProxy.Instance.OnApplicationDocumentClosed;
+ ControlledApplication.DocumentOpened += EventHandlerProxy.Instance.OnApplicationDocumentOpened;
}
private void UnsubscribeApplicationEvents()
{
UIControlledApplication.Idling -= OnApplicationIdle;
- UIControlledApplication.ViewActivated -= proxy.OnApplicationViewActivated;
- UIControlledApplication.ViewActivating -= proxy.OnApplicationViewActivating;
+ UIControlledApplication.ViewActivated -= EventHandlerProxy.Instance.OnApplicationViewActivated;
+ UIControlledApplication.ViewActivating -= EventHandlerProxy.Instance.OnApplicationViewActivating;
- ControlledApplication.DocumentClosing -= proxy.OnApplicationDocumentClosing;
- ControlledApplication.DocumentClosed -= proxy.OnApplicationDocumentClosed;
- ControlledApplication.DocumentOpened -= proxy.OnApplicationDocumentOpened;
+ ControlledApplication.DocumentClosing -= EventHandlerProxy.Instance.OnApplicationDocumentClosing;
+ ControlledApplication.DocumentClosed -= EventHandlerProxy.Instance.OnApplicationDocumentClosed;
+ ControlledApplication.DocumentOpened -= EventHandlerProxy.Instance.OnApplicationDocumentOpened;
- proxy = null;
+ EventHandlerProxy.Instance = null;
}
private void SubscribeAssemblyEvents()
@@ -333,35 +329,7 @@ private void UnsubscribeAssemblyEvents()
///
public static Assembly ResolveAssembly(object sender, ResolveEventArgs args)
{
- var assemblyPath = string.Empty;
- var assemblyName = new AssemblyName(args.Name).Name + ".dll";
-
- try
- {
- assemblyPath = Path.Combine(DynamoRevitApp.DynamoCorePath, assemblyName);
- if(File.Exists(assemblyPath))
- {
- return Assembly.LoadFrom(assemblyPath);
- }
-
- var assemblyLocation = Assembly.GetExecutingAssembly().Location;
- var assemblyDirectory = Path.GetDirectoryName(assemblyLocation);
-
- // Try "Dynamo 0.x\Revit_20xx" folder first...
- assemblyPath = Path.Combine(assemblyDirectory, assemblyName);
- if (!File.Exists(assemblyPath))
- {
- // If assembly cannot be found, try in "Dynamo 0.x" folder.
- var parentDirectory = Directory.GetParent(assemblyDirectory);
- assemblyPath = Path.Combine(parentDirectory.FullName, assemblyName);
- }
-
- return (File.Exists(assemblyPath) ? Assembly.LoadFrom(assemblyPath) : null);
- }
- catch (Exception ex)
- {
- throw new Exception(string.Format("The location of the assembly, {0} could not be resolved for loading.", assemblyPath), ex);
- }
+ return DynamoRevitAssemblyResolver.ResolveDynamoAssembly(DynamoCorePath, null, args);
}
private void SubscribeDocumentChangedEvent()
diff --git a/src/DynamoRevit/Models/RevitDynamoModel.cs b/src/DynamoRevit/Models/RevitDynamoModel.cs
index bb5e59564f..b2b160d954 100644
--- a/src/DynamoRevit/Models/RevitDynamoModel.cs
+++ b/src/DynamoRevit/Models/RevitDynamoModel.cs
@@ -8,8 +8,11 @@
using System.Windows.Forms;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Events;
+#if !DESIGN_AUTOMATION
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Events;
+using RevitServices.Threading;
+#endif
using Dynamo.Graph.Nodes;
using Dynamo.Graph.Nodes.ZeroTouch;
using Dynamo.Graph.Workspaces;
@@ -27,7 +30,6 @@
using RevitServices.Elements;
using RevitServices.Materials;
using RevitServices.Persistence;
-using RevitServices.Threading;
using RevitServices.Transactions;
using Category = Revit.Elements.Category;
using Element = Autodesk.Revit.DB.Element;
@@ -39,7 +41,9 @@ public class RevitDynamoModel : DynamoModel
{
public interface IRevitStartConfiguration : IStartConfiguration
{
+#if !DESIGN_AUTOMATION
DynamoRevitCommandData ExternalCommandData { get; set; }
+#endif
}
public struct RevitStartConfiguration : IRevitStartConfiguration
@@ -55,7 +59,9 @@ public struct RevitStartConfiguration : IRevitStartConfiguration
public string GeometryFactoryPath { get; set; }
public IAuthProvider AuthProvider { get; set; }
public string PackageManagerAddress { get; set; }
+#if !DESIGN_AUTOMATION
public DynamoRevitCommandData ExternalCommandData { get; set; }
+#endif
public IEnumerable Extensions { get; set; }
public TaskProcessMode ProcessMode { get; set; }
//the property will contain revit host information, to be passed on to Dynamo.
@@ -69,9 +75,10 @@ public struct RevitStartConfiguration : IRevitStartConfiguration
///
private bool updateCurrentUIDoc;
+#if !DESIGN_AUTOMATION
private readonly DynamoRevitCommandData externalCommandData;
-
- #region Events
+#endif
+#region Events
public event EventHandler RevitDocumentChanged;
@@ -155,7 +162,7 @@ protected override void OnWorkspaceAdded(WorkspaceModel workspace)
var dm = DocumentManager.Instance;
if (dm.CurrentDBDocument != null)
{
- SetRunEnabledBasedOnContext(dm.CurrentUIDocument.ActiveView);
+ SetRunEnabledBasedOnContext(dm.CurrentDBDocument.ActiveView);
}
}
@@ -185,7 +192,7 @@ public bool IsInMatchingDocumentContext
return false; // There's no current document stored.
// Selection is not allowed in perspective view mode.
- var view3D = dm.CurrentUIDocument.ActiveView as View3D;
+ var view3D = dm.CurrentDBDocument.ActiveView as View3D;
if ((view3D != null) && view3D.IsPerspective)
return false; // There's no view, or in perspective view.
@@ -216,12 +223,12 @@ private RevitDynamoModel(IRevitStartConfiguration configuration) :
base(configuration)
{
DisposeLogic.IsShuttingDown = false;
-
+#if !DESIGN_AUTOMATION
externalCommandData = configuration.ExternalCommandData;
-
+ SubscribeApplicationEvents(configuration.ExternalCommandData);
+#endif
SubscribeRevitServicesUpdaterEvents();
- SubscribeApplicationEvents(configuration.ExternalCommandData);
InitializeDocumentManager();
SubscribeDocumentManagerEvents();
SubscribeTransactionManagerEvents();
@@ -230,7 +237,7 @@ private RevitDynamoModel(IRevitStartConfiguration configuration) :
}
- #endregion
+#endregion
#region trace reconciliation
@@ -325,12 +332,14 @@ public override void PostTraceReconciliation(Dictionary> orph
}
else
{
+#if !DESIGN_AUTOMATION
// Delete all the orphans.
IdlePromise.ExecuteOnIdleAsync(
() =>
{
DeleteOrphanedElements(orphanedIds, Logger);
});
+#endif
}
}
@@ -422,7 +431,7 @@ private static void DeleteOrphanedElements(IEnumerable orphanedIds, ILog
}
}
- #endregion
+#endregion
#region Initialization
@@ -473,7 +482,7 @@ private void SetupPythonEngine(PythonEngine engine)
engine.EvaluationStarted += OnPythonEvalStart;
}
- catch(FileNotFoundException ex)
+ catch (FileNotFoundException ex)
{
Logger.Log(ex);
}
@@ -540,6 +549,7 @@ private void SetupPython()
internal void InitializeDocumentManager()
{
+#if !DESIGN_AUTOMATION
// Set the intitial document.
var activeUIDocument = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument;
if (activeUIDocument != null)
@@ -549,6 +559,7 @@ internal void InitializeDocumentManager()
OnRevitDocumentChanged();
}
+#endif
}
private static void InitializeMaterials()
@@ -556,10 +567,14 @@ private static void InitializeMaterials()
// Ensure that the current document has the needed materials
// and graphic styles to support visualization in Revit.
var mgr = MaterialsManager.Instance;
+#if !DESIGN_AUTOMATION
IdlePromise.ExecuteOnIdleAsync(mgr.InitializeForActiveDocumentOnIdle);
+#else
+ mgr.InitializeForActiveDocumentOnIdle();
+#endif
}
- #endregion
+#endregion
#region Event subscribe/unsubscribe
@@ -595,6 +610,7 @@ private void UnsubscribeDocumentManagerEvents()
DocumentManager.OnLogError -= Logger.Log;
}
+#if !DESIGN_AUTOMATION
private bool hasRegisteredApplicationEvents;
private void SubscribeApplicationEvents(DynamoRevitCommandData commandData)
{
@@ -603,11 +619,11 @@ private void SubscribeApplicationEvents(DynamoRevitCommandData commandData)
return;
}
- DynamoRevitApp.EventHandlerProxy.ViewActivating += OnApplicationViewActivating;
- DynamoRevitApp.EventHandlerProxy.ViewActivated += OnApplicationViewActivated;
- DynamoRevitApp.EventHandlerProxy.DocumentClosing += OnApplicationDocumentClosing;
- DynamoRevitApp.EventHandlerProxy.DocumentClosed += OnApplicationDocumentClosed;
- DynamoRevitApp.EventHandlerProxy.DocumentOpened += OnApplicationDocumentOpened;
+ RevitServices.EventHandler.EventHandlerProxy.Instance.ViewActivating += OnApplicationViewActivating;
+ RevitServices.EventHandler.EventHandlerProxy.Instance.ViewActivated += OnApplicationViewActivated;
+ RevitServices.EventHandler.EventHandlerProxy.Instance.DocumentClosing += OnApplicationDocumentClosing;
+ RevitServices.EventHandler.EventHandlerProxy.Instance.DocumentClosed += OnApplicationDocumentClosed;
+ RevitServices.EventHandler.EventHandlerProxy.Instance.DocumentOpened += OnApplicationDocumentOpened;
hasRegisteredApplicationEvents = true;
}
@@ -619,16 +635,17 @@ private void UnsubscribeApplicationEvents(DynamoRevitCommandData commandData)
return;
}
- DynamoRevitApp.EventHandlerProxy.ViewActivating -= OnApplicationViewActivating;
- DynamoRevitApp.EventHandlerProxy.ViewActivated -= OnApplicationViewActivated;
- DynamoRevitApp.EventHandlerProxy.DocumentClosing -= OnApplicationDocumentClosing;
- DynamoRevitApp.EventHandlerProxy.DocumentClosed -= OnApplicationDocumentClosed;
- DynamoRevitApp.EventHandlerProxy.DocumentOpened -= OnApplicationDocumentOpened;
+ RevitServices.EventHandler.EventHandlerProxy.Instance.ViewActivating -= OnApplicationViewActivating;
+ RevitServices.EventHandler.EventHandlerProxy.Instance.ViewActivated -= OnApplicationViewActivated;
+ RevitServices.EventHandler.EventHandlerProxy.Instance.DocumentClosing -= OnApplicationDocumentClosing;
+ RevitServices.EventHandler.EventHandlerProxy.Instance.DocumentClosed -= OnApplicationDocumentClosed;
+ RevitServices.EventHandler.EventHandlerProxy.Instance.DocumentOpened -= OnApplicationDocumentOpened;
hasRegisteredApplicationEvents = false;
}
+#endif
- #endregion
+#endregion
#region Application event handler
///
@@ -666,6 +683,7 @@ private void OnApplicationDocumentClosed(object sender, DocumentClosedEventArgs
HandleApplicationDocumentClosed();
}
+#if !DESIGN_AUTOMATION
///
/// Handler for Revit's ViewActivating event.
/// Addins are not available in some views in Revit, notably perspective views.
@@ -688,8 +706,8 @@ private void OnApplicationViewActivated(object sender, ViewActivatedEventArgs e)
{
HandleRevitViewActivated();
}
-
- #endregion
+#endif
+#endregion
#region Public methods
@@ -707,7 +725,11 @@ protected override void PreShutdownCore(bool shutdownHost)
{
if (shutdownHost)
{
+#if !DESIGN_AUTOMATION
DynamoRevitApp.AddIdleAction(ShutdownRevitHostOnce);
+#else
+ ShutdownRevitHostOnce();
+#endif
}
base.PreShutdownCore(shutdownHost);
@@ -715,7 +737,6 @@ protected override void PreShutdownCore(bool shutdownHost)
private static void ShutdownRevitHostOnce()
{
- var uiApplication = DocumentManager.Instance.CurrentUIApplication;
ShutdownRevitHost();
}
@@ -728,10 +749,13 @@ protected override void ShutDownCore(bool shutDownHost)
// unsubscribe events
RevitServicesUpdater.Instance.UnRegisterAllChangeHooks();
+#if !DESIGN_AUTOMATION
UnsubscribeApplicationEvents(externalCommandData);
+#endif
UnsubscribeDocumentManagerEvents();
UnsubscribeRevitServicesUpdaterEvents();
UnsubscribeTransactionManagerEvents();
+
PythonEngineManager.Instance.AvailableEngines.ToList().ForEach(engine => CleanUpPythonEngine(engine));
PythonEngineManager.Instance.AvailableEngines.CollectionChanged -= OnPythonEngineCollectionChanged;
@@ -741,9 +765,11 @@ protected override void ShutDownCore(bool shutDownHost)
protected override void PostShutdownCore(bool shutdownHost)
{
base.PostShutdownCore(shutdownHost);
-
+
+#if !DESIGN_AUTOMATION
// Always reset current UI document on shutdown
DocumentManager.Instance.CurrentUIDocument = null;
+#endif
}
///
@@ -830,7 +856,7 @@ var ws in Workspaces.OfType())
// If there is a current document, then set the run enabled
// state based on whether the view just activated is
// the same document.
- if (DocumentManager.Instance.CurrentUIDocument != null)
+ if (DocumentManager.Instance.CurrentDBDocument != null)
{
var newEnabled = newView != null &&
newView.Document.Equals(DocumentManager.Instance.CurrentDBDocument);
@@ -849,7 +875,7 @@ var ws in Workspaces.OfType())
}
}
- #endregion
+#endregion
#region Event handlers
@@ -863,14 +889,15 @@ private void HandleApplicationDocumentOpened()
// If the current document is null, for instance if there are
// no documents open, then set the current document, and
// present a message telling us where Dynamo is pointing.
- if (DocumentManager.Instance.CurrentUIDocument == null)
+ if (DocumentManager.Instance.CurrentDBDocument == null)
{
+#if !DESIGN_AUTOMATION
var activeUIDocument = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument;
DocumentManager.Instance.CurrentUIDocument = activeUIDocument;
if (activeUIDocument != null)
DocumentManager.Instance.HandleDocumentActivation(activeUIDocument.ActiveView);
-
+#endif
OnRevitDocumentChanged();
foreach (HomeWorkspaceModel ws in Workspaces.OfType())
@@ -901,6 +928,7 @@ private void HandleApplicationDocumentClosing(Document doc)
///
private void HandleApplicationDocumentClosed()
{
+#if !DESIGN_AUTOMATION
// If the active UI document is null, it means that all views have been
// closed from all document. Clear our reference, present a warning,
// and disable running.
@@ -933,6 +961,7 @@ private void HandleApplicationDocumentClosed()
{
SetRunEnabledBasedOnContext(uiDoc.ActiveView);
}
+#endif
}
///
@@ -944,11 +973,12 @@ private void HandleRevitViewActivated()
{
// If there is no active document, then set it to whatever
// document has just been activated
- if (DocumentManager.Instance.CurrentUIDocument == null)
+ if (DocumentManager.Instance.CurrentDBDocument == null)
{
+#if !DESIGN_AUTOMATION
DocumentManager.Instance.CurrentUIDocument =
DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument;
-
+#endif
OnRevitDocumentChanged();
InitializeMaterials();
@@ -974,6 +1004,7 @@ private void ResetForNewDocument()
private static void ShutdownRevitHost()
{
+#if !DESIGN_AUTOMATION
// this method cannot be called without Revit 2014
var exitCommand = RevitCommandId.LookupPostableCommandId(PostableCommand.ExitRevit);
var uiApplication = DocumentManager.Instance.CurrentUIApplication;
@@ -986,6 +1017,7 @@ private static void ShutdownRevitHost()
"A command in progress prevented Dynamo from " +
"closing revit. Dynamo update will be cancelled.");
}
+#endif
}
private void TransactionManager_FailuresRaised(FailuresAccessor failuresAccessor)
diff --git a/src/DynamoRevit/Properties/AssemblyInfo.cs b/src/DynamoRevit/Properties/AssemblyInfo.cs
index 5996d78d11..58ea1f6a8b 100644
--- a/src/DynamoRevit/Properties/AssemblyInfo.cs
+++ b/src/DynamoRevit/Properties/AssemblyInfo.cs
@@ -9,4 +9,5 @@
[assembly: AssemblyCulture("")]
[assembly: Guid("082cab33-cbc7-4e58-ae25-f0962f325d6e")]
[assembly: InternalsVisibleTo("RevitTestServices")]
-[assembly: InternalsVisibleTo("RevitSystemTests")]
\ No newline at end of file
+[assembly: InternalsVisibleTo("RevitSystemTests")]
+[assembly: InternalsVisibleTo("DADynamoApp")]
\ No newline at end of file
diff --git a/src/DynamoRevit/Utilities/ASMPreloader.cs b/src/DynamoRevit/Utilities/ASMPreloader.cs
new file mode 100644
index 0000000000..24c860cf06
--- /dev/null
+++ b/src/DynamoRevit/Utilities/ASMPreloader.cs
@@ -0,0 +1,91 @@
+using Autodesk.Revit.ApplicationServices;
+using DynamoInstallDetective;
+using System;
+using System.IO;
+using System.Reflection;
+using System.Text.RegularExpressions;
+
+namespace Dynamo.Applications
+{
+ internal static class ASMPrealoaderUtils
+ {
+ ///
+ /// Returns the version of ASM which is installed with Revit at the requested path.
+ /// This version number can be used to load the appropriate libG version.
+ ///
+ /// path where asm dlls are located, this is usually the product(Revit) install path
+ ///
+ internal static Version findRevitASMVersion(string asmLocation)
+ {
+ var lookup = new InstalledProductLookUp("Revit", "ASMAHL*.dll");
+ var product = lookup.GetProductFromInstallPath(asmLocation);
+ var libGversion = new Version(product.VersionInfo.Item1, product.VersionInfo.Item2, product.VersionInfo.Item3);
+ return libGversion;
+ }
+
+ // [Tech Debt] (Will refactor the code later)
+ ///
+ /// Return the preload version of LibG.
+ ///
+ ///
+ ///
+ internal static Version PreloadLibGVersion(string preloaderLocation)
+ {
+ preloaderLocation = new DirectoryInfo(preloaderLocation).Name;
+ var regExp = new Regex(@"^libg_(\d\d\d)_(\d)_(\d)$", RegexOptions.IgnoreCase);
+
+ var match = regExp.Match(preloaderLocation);
+ if (match.Groups.Count == 4)
+ {
+ return new Version(
+ Convert.ToInt32(match.Groups[1].Value),
+ Convert.ToInt32(match.Groups[2].Value),
+ Convert.ToInt32(match.Groups[3].Value));
+ }
+
+ return new Version();
+ }
+
+ internal static Version PreloadAsmFromRevit(string asmLocation, string dynamoCorePath)
+ {
+ Version libGVersion = findRevitASMVersion(asmLocation);
+ // Get the corresponding libG preloader location for the target ASM loading version.
+ // If there is exact match preloader version to the target ASM version, use it,
+ // otherwise use the closest below.
+ var preloaderLocation = DynamoShapeManager.Utilities.GetLibGPreloaderLocation(libGVersion, dynamoCorePath);
+
+ // [Tech Debt] (Will refactor the code later)
+ // The LibG version maybe different in Dynamo and Revit, using the one which is in Dynamo.
+ Version preLoadLibGVersion = PreloadLibGVersion(preloaderLocation);
+ DynamoShapeManager.Utilities.PreloadAsmFromPath(preloaderLocation, asmLocation);
+ return preLoadLibGVersion;
+ }
+
+
+ ///
+ /// DynamoShapeManager.dll is a companion assembly of Dynamo core components,
+ /// we do not want a static reference to it (since the Revit add-on can be
+ /// installed anywhere that's outside of Dynamo), we do not want a duplicated
+ /// reference to it. Here we use reflection to obtain GetGeometryFactoryPath
+ /// method, and call it to get the geometry factory assembly path.
+ ///
+ /// The path where DynamoShapeManager.dll can be
+ /// located.
+ /// The version of DynamoShapeManager.dll
+ /// Returns the full path to geometry factory assembly.
+ ///
+ public static string GetGeometryFactoryPath(string corePath, Version version)
+ {
+ var dynamoAsmPath = Path.Combine(corePath, "DynamoShapeManager.dll");
+ var assembly = Assembly.LoadFrom(dynamoAsmPath);
+ if (assembly == null)
+ throw new FileNotFoundException("File not found", dynamoAsmPath);
+
+ var utilities = assembly.GetType("DynamoShapeManager.Utilities");
+ var getGeometryFactoryPath = utilities.GetMethod("GetGeometryFactoryPath2");
+
+ return (getGeometryFactoryPath.Invoke(null,
+ new object[] { corePath, version }) as string);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/DynamoRevit/Utilities/DynamoRevitInternalNodes.cs b/src/DynamoRevit/Utilities/DynamoRevitInternalNodes.cs
new file mode 100644
index 0000000000..7b0460f5fa
--- /dev/null
+++ b/src/DynamoRevit/Utilities/DynamoRevitInternalNodes.cs
@@ -0,0 +1,123 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Xml.Serialization;
+
+namespace Dynamo.Applications
+{
+ ///
+ /// Defines parameters used for loading internal Dynamo Revit packages
+ ///
+ [Serializable()]
+ public class InternalPackage
+ {
+ ///
+ /// keeps the path to the node file
+ ///
+ public string NodePath { get; set; }
+
+ ///
+ /// keeps the path to the layoutSpecs.json file
+ ///
+ public string LayoutSpecsPath { get; set; }
+
+ ///
+ /// keeps paths to additional assembly load paths
+ ///
+ public List AdditionalAssemblyLoadPaths { get; set; }
+ }
+
+ internal static class DynamoRevitInternalNodes
+ {
+ private const string InternalNodesDir = "nodes";
+ private static IEnumerable GetAllInternalPackageFiles()
+ {
+ string currentAssemblyPath = Assembly.GetExecutingAssembly().Location;
+ string currentAssemblyDir = Path.GetDirectoryName(currentAssemblyPath);
+
+ string internalNodesDir = Path.Combine(currentAssemblyDir, InternalNodesDir);
+ if (false == Directory.Exists(internalNodesDir))
+ {
+ return new List();
+ }
+
+ string[] internalNodesFolders = Directory.GetDirectories(internalNodesDir);
+
+ List internalPackageFiles = new List();
+ foreach (string dir in internalNodesFolders)
+ {
+ string internalPackageFile = Path.Combine(dir, "internalPackage.xml");
+ if (true == File.Exists(internalPackageFile))
+ {
+ internalPackageFiles.Add(internalPackageFile);
+ }
+ }
+ return internalPackageFiles;
+ }
+ private static IEnumerable ParseinternalPackageFiles(IEnumerable internalPackageFiles)
+ {
+ List internalPackages = new List();
+ string basePath = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
+
+ foreach (string internalPackageFile in internalPackageFiles)
+ {
+ try
+ {
+ string internalPackageDir = Path.GetDirectoryName(internalPackageFile);
+ using (StreamReader reader = new StreamReader(internalPackageFile))
+ {
+ XmlSerializer serializer = new XmlSerializer(typeof(InternalPackage));
+ InternalPackage intPackage = serializer.Deserialize(reader) as InternalPackage;
+
+ // convert to absolute path, if needed
+ if (false == Path.IsPathRooted(intPackage.NodePath))
+ {
+ intPackage.NodePath = Path.Combine(internalPackageDir, intPackage.NodePath);
+ }
+
+ // convert to absolute path, if needed
+ if (false == Path.IsPathRooted(intPackage.LayoutSpecsPath))
+ {
+ intPackage.LayoutSpecsPath = Path.Combine(internalPackageDir, intPackage.LayoutSpecsPath);
+ }
+
+ // convert to absolute paths, if needed
+ if (null != intPackage.AdditionalAssemblyLoadPaths && intPackage.AdditionalAssemblyLoadPaths.Count > 0)
+ {
+ intPackage.AdditionalAssemblyLoadPaths = intPackage.AdditionalAssemblyLoadPaths
+ .Select(p => !Path.IsPathRooted(p) ? Path.Combine(basePath, p) : p)
+ .Where(Path.Exists).ToList();
+ }
+
+ internalPackages.Add(intPackage);
+ }
+ }
+ catch (Exception)
+ {
+ Console.WriteLine(string.Format("Exception while trying to parse internalPackage file {0}", internalPackageFile));
+ }
+ }
+
+ return internalPackages;
+ }
+ internal static IEnumerable GetNodesToPreload()
+ {
+ IEnumerable internalPackageFiles = GetAllInternalPackageFiles();
+ return ParseinternalPackageFiles(internalPackageFiles).Select(pkg => pkg.NodePath);
+ }
+ internal static IEnumerable GetLayoutSpecsFiles()
+ {
+ IEnumerable internalPackageFiles = GetAllInternalPackageFiles();
+ return ParseinternalPackageFiles(internalPackageFiles).Select(pkg => pkg.LayoutSpecsPath);
+ }
+
+ internal static IEnumerable GetAdditionalAssemblyLoadPaths()
+ {
+ IEnumerable internalPackageFiles = GetAllInternalPackageFiles();
+ return ParseinternalPackageFiles(internalPackageFiles).SelectMany(pkg => pkg.AdditionalAssemblyLoadPaths);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/DynamoRevit/Utilities/internal class DynamoRevitAssemblyResolver.cs b/src/DynamoRevit/Utilities/internal class DynamoRevitAssemblyResolver.cs
new file mode 100644
index 0000000000..bd9f2acbab
--- /dev/null
+++ b/src/DynamoRevit/Utilities/internal class DynamoRevitAssemblyResolver.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+
+internal class DynamoRevitAssemblyResolver
+{
+ ///
+ /// Handler to the ApplicationDomain's AssemblyResolve event.
+ /// If an assembly's location cannot be resolved, an exception is
+ /// thrown. Failure to resolve an assembly will leave Dynamo in
+ /// a bad state, so we should throw an exception here which gets caught
+ /// by our unhandled exception handler and presents the crash dialogue.
+ ///
+ ///
+ ///
+ ///
+ internal static Assembly ResolveDynamoAssembly(string dynamoCorePath, List additionalPaths, ResolveEventArgs args)
+ {
+ var assemblyPath = string.Empty;
+ var assemblyName = new AssemblyName(args.Name).Name + ".dll";
+
+ try
+ {
+ assemblyPath = Path.Combine(dynamoCorePath, assemblyName);
+ if (File.Exists(assemblyPath))
+ {
+ return Assembly.LoadFrom(assemblyPath);
+ }
+
+ if (additionalPaths != null)
+ {
+ foreach (var additionalPath in additionalPaths)
+ {
+ assemblyPath = Path.Combine(additionalPath, assemblyName);
+ if (File.Exists(assemblyPath))
+ {
+ return Assembly.LoadFrom(assemblyPath);
+ }
+ }
+ }
+
+ var assemblyLocation = Assembly.GetExecutingAssembly().Location;
+ var assemblyDirectory = Path.GetDirectoryName(assemblyLocation);
+
+ // Try "Dynamo 0.x\Revit_20xx" folder first...
+ assemblyPath = Path.Combine(assemblyDirectory, assemblyName);
+ if (!File.Exists(assemblyPath))
+ {
+ // If assembly cannot be found, try in "Dynamo 0.x" folder.
+ var parentDirectory = Directory.GetParent(assemblyDirectory);
+ assemblyPath = Path.Combine(parentDirectory.FullName, assemblyName);
+ }
+
+ return (File.Exists(assemblyPath) ? Assembly.LoadFrom(assemblyPath) : null);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message + ex.StackTrace);
+ throw new Exception(string.Format("The location of the assembly, {0} could not be resolved for loading.", assemblyPath), ex);
+ }
+ }
+}
diff --git a/src/DynamoRevitIcons/DynamoRevitIcons.csproj b/src/DynamoRevitIcons/DynamoRevitIcons.csproj
index 730d043221..420827688c 100644
--- a/src/DynamoRevitIcons/DynamoRevitIcons.csproj
+++ b/src/DynamoRevitIcons/DynamoRevitIcons.csproj
@@ -7,16 +7,6 @@
prompt
4
-
- full
- false
- TRACE;DEBUG;ENABLE_DYNAMO_SCHEDULER
-
-
- pdbonly
- true
- TRACE
-
true
diff --git a/src/Libraries/Migrations/Migrations.csproj b/src/Libraries/Migrations/Migrations.csproj
index 24d523a8a7..377b84b838 100644
--- a/src/Libraries/Migrations/Migrations.csproj
+++ b/src/Libraries/Migrations/Migrations.csproj
@@ -7,22 +7,8 @@
true
true
$(NoWarn);CS3001;CS3002
- prompt
- 4
- false
$(OutputPath)\nodes\
-
- true
- full
- false
- DEBUG;TRACE
-
-
- pdbonly
- true
- TRACE
-
diff --git a/src/Libraries/RevitNodes/Elements/AdaptiveComponent.cs b/src/Libraries/RevitNodes/Elements/AdaptiveComponent.cs
index aed5db9d5b..772a1ff3af 100644
--- a/src/Libraries/RevitNodes/Elements/AdaptiveComponent.cs
+++ b/src/Libraries/RevitNodes/Elements/AdaptiveComponent.cs
@@ -570,7 +570,7 @@ private static AdaptiveComponent[] InternalByPoints(Point[][] points, FamilyType
throw new Exception(string.Format(Properties.Resources.DesiredNumberOfPoints, i, desiredNumOfPoints, numOfPoints));
}
- var creationData = DocumentManager.Instance.CurrentUIApplication.Application.Create.
+ var creationData = DocumentManager.Instance.CurrentDBDocument.Application.Create.
NewFamilyInstanceCreationData(familyType.InternalFamilySymbol, aPoints);
if (creationData != null)
diff --git a/src/Libraries/RevitNodes/Elements/CeilingType.cs b/src/Libraries/RevitNodes/Elements/CeilingType.cs
index e394aec749..f2d36b0ba2 100644
--- a/src/Libraries/RevitNodes/Elements/CeilingType.cs
+++ b/src/Libraries/RevitNodes/Elements/CeilingType.cs
@@ -123,7 +123,8 @@ public Dictionary GetThermalProperties()
return new Dictionary
{
{ absorptanceOutputPort, thermalProperties.Absorptance },
- { thermalTransmittanceOutputPort, thermalProperties.ThermalTransmittance },
+ // TODO: reconcile for Design Automation
+ //{ thermalTransmittanceOutputPort, thermalProperties.ThermalTransmittance },
{ roughnessOutputPort, thermalProperties.Roughness },
{ thermalMassOutputPort, thermalProperties.ThermalMass },
{ thermalResistanceOutputPort, thermalProperties.ThermalResistance }
diff --git a/src/Libraries/RevitNodes/Elements/Element.cs b/src/Libraries/RevitNodes/Elements/Element.cs
index 4216eb78ba..6a349ff810 100644
--- a/src/Libraries/RevitNodes/Elements/Element.cs
+++ b/src/Libraries/RevitNodes/Elements/Element.cs
@@ -287,6 +287,7 @@ public virtual void Dispose()
// Do not delete Revit owned elements
if (!IsRevitOwned && remainingBindings == 0 && !didRevitDelete)
{
+#if !DESIGN_AUTOMATION
if(this.InternalElement is View && InternalElement.IsValidObject)
{
Autodesk.Revit.UI.UIDocument uIDocument = new Autodesk.Revit.UI.UIDocument(Document);
@@ -300,6 +301,7 @@ public virtual void Dispose()
throw new InvalidOperationException(string.Format(Properties.Resources.CantCloseLastOpenView, this.ToString()));
}
}
+#endif
DocumentManager.Instance.DeleteElement(new ElementUUID(InternalUniqueId));
}
else
@@ -492,7 +494,7 @@ public Element SetParameterByName(string parameterName, object value)
public Element OverrideColorInView(Color color)
{
TransactionManager.Instance.EnsureInTransaction(DocumentManager.Instance.CurrentDBDocument);
- var view = DocumentManager.Instance.CurrentUIDocument.ActiveView;
+ var view = DocumentManager.Instance.CurrentDBDocument.ActiveView;
var ogs = new Autodesk.Revit.DB.OverrideGraphicSettings();
var patternCollector = new FilteredElementCollector(DocumentManager.Instance.CurrentDBDocument);
@@ -518,7 +520,7 @@ public Element OverrideColorInView(Color color)
public Element OverrideInView(Revit.Filter.OverrideGraphicSettings overrides, bool hide = false)
{
TransactionManager.Instance.EnsureInTransaction(DocumentManager.Instance.CurrentDBDocument);
- var view = DocumentManager.Instance.CurrentUIDocument.ActiveView;
+ var view = DocumentManager.Instance.CurrentDBDocument.ActiveView;
view.SetElementOverrides(InternalElementId, overrides.InternalOverrideGraphicSettings);
if (hide) view.HideElements(new List() { InternalElementId });
else view.UnhideElements(new List() { InternalElementId });
@@ -534,7 +536,7 @@ public Revit.Filter.OverrideGraphicSettings OverridesInView
{
get
{
- var view = DocumentManager.Instance.CurrentUIDocument.ActiveView;
+ var view = DocumentManager.Instance.CurrentDBDocument.ActiveView;
return new Filter.OverrideGraphicSettings(view.GetElementOverrides(InternalElementId));
}
diff --git a/src/Libraries/RevitNodes/Elements/FloorType.cs b/src/Libraries/RevitNodes/Elements/FloorType.cs
index 6179e61adf..42664b6299 100644
--- a/src/Libraries/RevitNodes/Elements/FloorType.cs
+++ b/src/Libraries/RevitNodes/Elements/FloorType.cs
@@ -144,7 +144,8 @@ public Dictionary GetThermalProperties()
return new Dictionary
{
{ absorptanceOutputPort, thermalProperties.Absorptance },
- { thermalTransmittanceOutputPort, thermalProperties.ThermalTransmittance },
+ // TODO: reconcile for Design Automation
+ //{ thermalTransmittanceOutputPort, thermalProperties.ThermalTransmittance },
{ roughnessOutputPort, thermalProperties.Roughness },
{ thermalMassOutputPort, thermalProperties.ThermalMass },
{ thermalResistanceOutputPort, thermalProperties.ThermalResistance }
diff --git a/src/Libraries/RevitNodes/Elements/LinkElement.cs b/src/Libraries/RevitNodes/Elements/LinkElement.cs
index bca2639e9a..514bb95c1c 100644
--- a/src/Libraries/RevitNodes/Elements/LinkElement.cs
+++ b/src/Libraries/RevitNodes/Elements/LinkElement.cs
@@ -50,12 +50,12 @@ public static class LinkElement
}
return matchingLinkInstances;
}
-
+ // TODO: move to a UI library
+#if !DESIGN_AUTOMATION
// helper for zooming to clicked green Id
internal static void ZoomToLinkedElement(Element element)
{
-
UIDocument uiDoc = DocumentManager.Instance.CurrentUIDocument;
Autodesk.Revit.DB.View activeView = uiDoc.ActiveView;
// get active UI view to use
@@ -65,12 +65,12 @@ internal static void ZoomToLinkedElement(Element element)
// use the center of the BoundingBox as zoom center
BoundingBoxXYZ bb = element.InternalElement.get_BoundingBox(null);
// if the BBox cannot be found, attempt to find it using the active view
- if (bb==null)
+ if (bb == null)
{
- bb=element.InternalElement.get_BoundingBox(activeView);
+ bb = element.InternalElement.get_BoundingBox(activeView);
}
// finally, if the BB cannot be found at all
- if (bb==null)
+ if (bb == null)
{
TaskDialog.Show("Revit", "No good view can be found.");
return;
@@ -88,6 +88,7 @@ internal static void ZoomToLinkedElement(Element element)
uiview.ZoomAndCenterRectangle(min, max);
}
}
+#endif
// helper to return element's location with transform
internal static object GetLinkElementLocation(Element linkElement)
@@ -215,7 +216,8 @@ public static object GetGeometry(Element linkedElement, string detailLevel = "Me
newVertList.Add(transformedVertex);
}
- var newMesh = Autodesk.DesignScript.Geometry.Mesh.ByPointsIndexGroups(newVertList, meshIndices);
+ // TODO: reconcile for Design Automation
+ Autodesk.DesignScript.Geometry.Mesh newMesh = null;// Autodesk.DesignScript.Geometry.Mesh.ByPointsIndexGroups(newVertList, meshIndices);
geoSet.Add(newMesh);
break;
case GeometryInstance gi:
diff --git a/src/Libraries/RevitNodes/Elements/RoofType.cs b/src/Libraries/RevitNodes/Elements/RoofType.cs
index 8a7bb56f95..ff7c62a746 100644
--- a/src/Libraries/RevitNodes/Elements/RoofType.cs
+++ b/src/Libraries/RevitNodes/Elements/RoofType.cs
@@ -123,7 +123,8 @@ public Dictionary GetThermalProperties()
return new Dictionary
{
{ absorptanceOutputPort, thermalProperties.Absorptance },
- { thermalTransmittanceOutputPort, thermalProperties.ThermalTransmittance },
+ // TODO: reconcile for Design Automation
+ //{ thermalTransmittanceOutputPort, thermalProperties.ThermalTransmittance },
{ roughnessOutputPort, thermalProperties.Roughness },
{ thermalMassOutputPort, thermalProperties.ThermalMass },
{ thermalResistanceOutputPort, thermalProperties.ThermalResistance }
diff --git a/src/Libraries/RevitNodes/Elements/Views/Sheet.cs b/src/Libraries/RevitNodes/Elements/Views/Sheet.cs
index b28407d482..34d73a7fb7 100644
--- a/src/Libraries/RevitNodes/Elements/Views/Sheet.cs
+++ b/src/Libraries/RevitNodes/Elements/Views/Sheet.cs
@@ -773,6 +773,7 @@ public static Sheet DuplicateSheet(Sheet sheet, bool duplicateWithContents = fal
}
}
}
+#if !DESIGN_AUTOMATION
if(newSheet == null)
{
Autodesk.Revit.UI.UIDocument uIDocument = new Autodesk.Revit.UI.UIDocument(Document);
@@ -789,7 +790,8 @@ public static Sheet DuplicateSheet(Sheet sheet, bool duplicateWithContents = fal
}
}
Document.Delete(elementIds);
- }
+ }
+#endif
}
if (newSheet == null && TraceElements.Count == 0)
@@ -842,7 +844,7 @@ public static Sheet DuplicateSheet(Sheet sheet, bool duplicateWithContents = fal
return newSheet;
}
- #endregion
+#endregion
#region Internal static constructors
diff --git a/src/Libraries/RevitNodes/Elements/Views/StructuralPlanView.cs b/src/Libraries/RevitNodes/Elements/Views/StructuralPlanView.cs
index a59fd464ff..a0f51fe807 100644
--- a/src/Libraries/RevitNodes/Elements/Views/StructuralPlanView.cs
+++ b/src/Libraries/RevitNodes/Elements/Views/StructuralPlanView.cs
@@ -72,7 +72,7 @@ private void InitStructuralPlanView(Autodesk.Revit.DB.Level level)
/// A StructuralPlanView if successful.
public static StructuralPlanView ByLevel(Level level)
{
- if (!DocumentManager.Instance.CurrentUIApplication.Application.IsStructureEnabled)
+ if (!DocumentManager.Instance.CurrentDBDocument.Application.IsStructureEnabled)
{
throw new InvalidOperationException(Properties.Resources.StructuralPlanNotEnabled);
}
diff --git a/src/Libraries/RevitNodes/Elements/Views/View.cs b/src/Libraries/RevitNodes/Elements/Views/View.cs
index f8ab6d7cc6..5050e95d26 100644
--- a/src/Libraries/RevitNodes/Elements/Views/View.cs
+++ b/src/Libraries/RevitNodes/Elements/Views/View.cs
@@ -618,6 +618,8 @@ public static Revit.Elements.Views.View DuplicateView(View view, string viewDupl
{
newViewName = prefix + view.Name + suffix;
}
+
+#if !DESIGN_AUTOMATION
Autodesk.Revit.UI.UIDocument uIDocument = new Autodesk.Revit.UI.UIDocument(Document);
var openedViews = uIDocument.GetOpenUIViews().ToList();
@@ -630,6 +632,7 @@ public static Revit.Elements.Views.View DuplicateView(View view, string viewDupl
else
count--;
}
+#endif
if (count == 0)
{
@@ -651,6 +654,7 @@ public static Revit.Elements.Views.View DuplicateView(View view, string viewDupl
var param = newView.InternalView.get_Parameter(BuiltInParameter.VIEW_NAME);
param.Set(newViewName);
}
+#if !DESIGN_AUTOMATION
if (viewElement != null)
{
var shouldClosedViews = openedViews.FindAll(x => viewElement.Id == x.ViewId);
@@ -664,7 +668,8 @@ public static Revit.Elements.Views.View DuplicateView(View view, string viewDupl
throw new InvalidOperationException(string.Format(Properties.Resources.CantCloseLastOpenView, viewElement.ToString()));
}
}
- }
+ }
+#endif
}
ElementBinder.CleanupAndSetElementForTrace(Document, newView.InternalElement);
@@ -704,7 +709,7 @@ private static Boolean CheckUniqueViewName(String viewName)
return IsUnique;
}
- #endregion
+#endregion
#region CropBox
diff --git a/src/Libraries/RevitNodes/Elements/WallType.cs b/src/Libraries/RevitNodes/Elements/WallType.cs
index 9eeb873298..46d8569c01 100644
--- a/src/Libraries/RevitNodes/Elements/WallType.cs
+++ b/src/Libraries/RevitNodes/Elements/WallType.cs
@@ -140,7 +140,8 @@ public Dictionary GetThermalProperties()
return new Dictionary
{
{ absorptanceOutputPort, thermalProperties.Absorptance },
- { thermalTransmittanceOutputPort, thermalProperties.ThermalTransmittance },
+ // TODO: reconcile for Design Automation
+ //{ thermalTransmittanceOutputPort, thermalProperties.ThermalTransmittance },
{ roughnessOutputPort, thermalProperties.Roughness },
{ thermalMassOutputPort, thermalProperties.ThermalMass },
{ thermalResistanceOutputPort, thermalProperties.ThermalResistance }
diff --git a/src/Libraries/RevitNodes/GeometryConversion/RevitToProtoMesh.cs b/src/Libraries/RevitNodes/GeometryConversion/RevitToProtoMesh.cs
index f54d3ce833..3933035e91 100644
--- a/src/Libraries/RevitNodes/GeometryConversion/RevitToProtoMesh.cs
+++ b/src/Libraries/RevitNodes/GeometryConversion/RevitToProtoMesh.cs
@@ -18,7 +18,8 @@ public static Autodesk.DesignScript.Geometry.Mesh ToProtoType(this Autodesk.Revi
.Select(mesh.get_Triangle)
.Select(tri => IndexGroup.ByIndices(tri.get_Index(0), tri.get_Index(1), tri.get_Index(2)));
- return Autodesk.DesignScript.Geometry.Mesh.ByPointsIndexGroups(pts, tris);
+ // TODO: reconcile for Design Automation
+ return null;// Autodesk.DesignScript.Geometry.Mesh.ByPointsIndexGroups(pts, tris);
}
diff --git a/src/Libraries/RevitNodes/Properties/AssemblyInfo.cs b/src/Libraries/RevitNodes/Properties/AssemblyInfo.cs
index 1d6207cd65..31666a56c9 100644
--- a/src/Libraries/RevitNodes/Properties/AssemblyInfo.cs
+++ b/src/Libraries/RevitNodes/Properties/AssemblyInfo.cs
@@ -6,3 +6,4 @@
[assembly: Guid("17f8f9d8-c00e-4c11-9eb1-06a716689de9")]
[assembly: InternalsVisibleTo("RevitNodesTests")]
[assembly: InternalsVisibleTo("DynamoRevitDS")]
+[assembly: InternalsVisibleTo("DADynamoApp")]
diff --git a/src/Libraries/RevitNodes/RevitNodes.csproj b/src/Libraries/RevitNodes/RevitNodes.csproj
index 4d9940c1cf..1a2b42f9e0 100644
--- a/src/Libraries/RevitNodes/RevitNodes.csproj
+++ b/src/Libraries/RevitNodes/RevitNodes.csproj
@@ -8,9 +8,6 @@
false
$(OutputPath)\$(UICulture)\RevitNodes.xml
$(NoWarn);1591;CA2200
- false
- prompt
- 4
DSRevitNodes
true
true
@@ -18,16 +15,6 @@
None
-
- full
- false
- DEBUG;TRACE
-
-
- pdbonly
- true
- TRACE
-
diff --git a/src/Libraries/RevitNodes/Transaction/Transaction.cs b/src/Libraries/RevitNodes/Transaction/Transaction.cs
index fbafb5faab..8d67caa323 100644
--- a/src/Libraries/RevitNodes/Transaction/Transaction.cs
+++ b/src/Libraries/RevitNodes/Transaction/Transaction.cs
@@ -30,7 +30,9 @@ public static object Start(object input)
public static object End(object input)
{
TransactionManager.Instance.ForceCloseTransaction();
+#if !DESIGN_AUTOMATION
DocumentManager.Instance.CurrentUIDocument.RefreshActiveView();
+#endif
return input;
}
}
diff --git a/src/Libraries/RevitNodesUI/Elements.cs b/src/Libraries/RevitNodesUI/Elements.cs
index 43050bb310..5207504224 100644
--- a/src/Libraries/RevitNodesUI/Elements.cs
+++ b/src/Libraries/RevitNodesUI/Elements.cs
@@ -28,6 +28,7 @@
using BuiltinNodeCategories = Revit.Elements.BuiltinNodeCategories;
using View = Revit.Elements.Views.View;
using RevitServices.Transactions;
+using Autodesk.Revit.ApplicationServices;
namespace DSRevitNodesUI
{
@@ -281,8 +282,10 @@ public ElementsInView()
OutPorts.Add(new PortModel(PortType.Output, this, new PortData("elements", Properties.Resources.PortDataAllVisibleElementsToolTip)));
RegisterAllPorts();
- DynamoRevitApp.EventHandlerProxy.ViewActivated += RevitDynamoModel_RevitDocumentChanged;
- DynamoRevitApp.EventHandlerProxy.DocumentOpened += RevitDynamoModel_RevitDocumentChanged;
+#if !DESIGN_AUTOMATION
+ RevitServices.EventHandler.EventHandlerProxy.Instance.ViewActivated += RevitDynamoModel_RevitDocumentChanged;
+#endif
+ RevitServices.EventHandler.EventHandlerProxy.Instance.DocumentOpened += RevitDynamoModel_RevitDocumentChanged;
RevitServicesUpdater.Instance.ElementsUpdated += RevitServicesUpdaterOnElementsUpdated;
RevitDynamoModel_RevitDocumentChanged(null, null);
@@ -291,8 +294,10 @@ public ElementsInView()
[JsonConstructor]
public ElementsInView(IEnumerable inPorts, IEnumerable outPorts) : base(inPorts, outPorts)
{
- DynamoRevitApp.EventHandlerProxy.ViewActivated += RevitDynamoModel_RevitDocumentChanged;
- DynamoRevitApp.EventHandlerProxy.DocumentOpened += RevitDynamoModel_RevitDocumentChanged;
+#if !DESIGN_AUTOMATION
+ RevitServices.EventHandler.EventHandlerProxy.Instance.ViewActivated += RevitDynamoModel_RevitDocumentChanged;
+#endif
+ RevitServices.EventHandler.EventHandlerProxy.Instance.DocumentOpened += RevitDynamoModel_RevitDocumentChanged;
RevitServicesUpdater.Instance.ElementsUpdated += RevitServicesUpdaterOnElementsUpdated;
RevitDynamoModel_RevitDocumentChanged(null, null);
@@ -300,8 +305,10 @@ public ElementsInView(IEnumerable inPorts, IEnumerable out
public override void Dispose()
{
- DynamoRevitApp.EventHandlerProxy.ViewActivated -= RevitDynamoModel_RevitDocumentChanged;
- DynamoRevitApp.EventHandlerProxy.DocumentOpened -= RevitDynamoModel_RevitDocumentChanged;
+#if !DESIGN_AUTOMATION
+ RevitServices.EventHandler.EventHandlerProxy.Instance.ViewActivated -= RevitDynamoModel_RevitDocumentChanged;
+#endif
+ RevitServices.EventHandler.EventHandlerProxy.Instance.DocumentOpened -= RevitDynamoModel_RevitDocumentChanged;
RevitServicesUpdater.Instance.ElementsUpdated -= RevitServicesUpdaterOnElementsUpdated;
diff --git a/src/Libraries/RevitNodesUI/RevitDropDown.cs b/src/Libraries/RevitNodesUI/RevitDropDown.cs
index 7d151fc264..f32bebec47 100644
--- a/src/Libraries/RevitNodesUI/RevitDropDown.cs
+++ b/src/Libraries/RevitNodesUI/RevitDropDown.cs
@@ -48,14 +48,14 @@ public abstract class RevitDropDownBase : DSDropDownBase
protected RevitDropDownBase(string value) : base(value)
{
RevitServicesUpdater.Instance.ElementsUpdated += Updater_ElementsUpdated;
- DynamoRevitApp.EventHandlerProxy.DocumentOpened += Controller_RevitDocumentChanged;
+ RevitServices.EventHandler.EventHandlerProxy.Instance.DocumentOpened += Controller_RevitDocumentChanged;
}
[JsonConstructor]
public RevitDropDownBase(string value, IEnumerable inPorts, IEnumerable outPorts) : base(value, inPorts, outPorts)
{
RevitServicesUpdater.Instance.ElementsUpdated += Updater_ElementsUpdated;
- DynamoRevitApp.EventHandlerProxy.DocumentOpened += Controller_RevitDocumentChanged;
+ RevitServices.EventHandler.EventHandlerProxy.Instance.DocumentOpened += Controller_RevitDocumentChanged;
}
void Controller_RevitDocumentChanged(object sender, EventArgs e)
@@ -90,7 +90,7 @@ private void Updater_ElementsUpdated(object sender, ElementUpdateEventArgs e)
public override void Dispose()
{
RevitServicesUpdater.Instance.ElementsUpdated -= Updater_ElementsUpdated;
- DynamoRevitApp.EventHandlerProxy.DocumentOpened -= Controller_RevitDocumentChanged;
+ RevitServices.EventHandler.EventHandlerProxy.Instance.DocumentOpened -= Controller_RevitDocumentChanged;
base.Dispose();
}
diff --git a/src/Libraries/RevitNodesUI/RevitNodesUI.csproj b/src/Libraries/RevitNodesUI/RevitNodesUI.csproj
index e4a62734e3..fa7c8d9f73 100644
--- a/src/Libraries/RevitNodesUI/RevitNodesUI.csproj
+++ b/src/Libraries/RevitNodesUI/RevitNodesUI.csproj
@@ -1,32 +1,31 @@
-
-
-
-
- DSRevitNodesUI
- DSRevitNodesUI
- $(OutputPath)\nodes\
- prompt
- 4
- false
- true
- false
-
-
-
- true
- full
- false
- DEBUG;TRACE
-
-
- pdbonly
- true
- TRACE
-
-
-
-
+
+
+
+
+ DSRevitNodesUI
+ DSRevitNodesUI
+ $(OutputPath)\nodes\
+ true
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
$(REVITAPI)\RevitAPI.dll
@@ -36,9 +35,9 @@
$(REVITAPI)\RevitAPIUI.dll
False
-
-
+
+
ComboControl.xaml
@@ -56,7 +55,7 @@
-
+
False
diff --git a/src/Libraries/RevitNodesUI/RevitTypes.cs b/src/Libraries/RevitNodesUI/RevitTypes.cs
index f4bc73c43a..7bbb3eb98f 100644
--- a/src/Libraries/RevitNodesUI/RevitTypes.cs
+++ b/src/Libraries/RevitNodesUI/RevitTypes.cs
@@ -1,20 +1,7 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
using Newtonsoft.Json;
-using Autodesk.DesignScript.Geometry;
-using Autodesk.DesignScript.Runtime;
-using DSRevitNodesUI;
-using RVT = Autodesk.Revit.DB;
-using RevitServices.Persistence;
-using RevitServices.Transactions;
-
-using Dynamo.Utilities;
-using Dynamo.Models;
-using Dynamo.Nodes;
using ProtoCore.AST.AssociativeAST;
-using CoreNodeModels.Properties;
using Dynamo.Graph.Nodes;
namespace DSRevitNodesUI
diff --git a/src/Libraries/RevitNodesUI/Selection.cs b/src/Libraries/RevitNodesUI/Selection.cs
index a2eecc2011..081ab4b91b 100644
--- a/src/Libraries/RevitNodesUI/Selection.cs
+++ b/src/Libraries/RevitNodesUI/Selection.cs
@@ -161,7 +161,7 @@ protected RevitSelection(SelectionType selectionType,
: base(selectionType, selectionObjectType, message, prefix)
{
RevitServicesUpdater.Instance.ElementsUpdated += Updater_ElementsUpdated;
- DynamoRevitApp.EventHandlerProxy.DocumentOpened += Controller_RevitDocumentChanged;
+ RevitServices.EventHandler.EventHandlerProxy.Instance.DocumentOpened += Controller_RevitDocumentChanged;
}
[JsonConstructor]
@@ -171,7 +171,7 @@ public RevitSelection(SelectionType selectionType,
: base(selectionType, selectionObjectType, message, prefix, selectionIdentifier, inPorts, outPorts)
{
RevitServicesUpdater.Instance.ElementsUpdated += Updater_ElementsUpdated;
- DynamoRevitApp.EventHandlerProxy.DocumentOpened += Controller_RevitDocumentChanged;
+ RevitServices.EventHandler.EventHandlerProxy.Instance.DocumentOpened += Controller_RevitDocumentChanged;
}
#endregion
@@ -192,7 +192,7 @@ public override void Dispose()
base.Dispose();
RevitServicesUpdater.Instance.ElementsUpdated -= Updater_ElementsUpdated;
- DynamoRevitApp.EventHandlerProxy.DocumentOpened -= Controller_RevitDocumentChanged;
+ RevitServices.EventHandler.EventHandlerProxy.Instance.DocumentOpened -= Controller_RevitDocumentChanged;
if (revitDynamoModel != null)
{
diff --git a/src/Libraries/RevitNodesUI/SiteLocation.cs b/src/Libraries/RevitNodesUI/SiteLocation.cs
index 397696e066..5b1c081a13 100644
--- a/src/Libraries/RevitNodesUI/SiteLocation.cs
+++ b/src/Libraries/RevitNodesUI/SiteLocation.cs
@@ -1,8 +1,10 @@
using Dynamo.Applications;
using Dynamo.Applications.Models;
+#if !DESIGN_AUTOMATION
using Dynamo.Controls;
-using Dynamo.Graph.Nodes;
using Dynamo.Wpf;
+#endif
+using Dynamo.Graph.Nodes;
using Newtonsoft.Json;
using ProtoCore.AST.AssociativeAST;
using Revit.GeometryConversion;
@@ -15,7 +17,8 @@
namespace DSRevitNodesUI
{
- public class SiteLocationNodeViewCustomization : INodeViewCustomization
+#if !DESIGN_AUTOMATION
+ public class SiteLocationNodeViewCustomization : INodeViewCustomization
{
public void CustomizeView(SiteLocation model, NodeView nodeView)
{
@@ -28,6 +31,7 @@ public void Dispose()
}
}
+#endif
[NodeName("SiteLocation"), NodeCategory(BuiltinNodeCategories.ANALYZE),
NodeDescription("SiteLocationDescription", typeof(Properties.Resources)), IsDesignScriptCompatible]
@@ -47,10 +51,12 @@ public SiteLocation()
ArgumentLacing = LacingStrategy.Disabled;
- DynamoRevitApp.EventHandlerProxy.DocumentOpened += model_RevitDocumentChanged;
+ RevitServices.EventHandler.EventHandlerProxy.Instance.DocumentOpened += model_RevitDocumentChanged;
RevitServicesUpdater.Instance.ElementsUpdated += RevitServicesUpdater_ElementsUpdated;
-
+
+#if !DESIGN_AUTOMATION
DynamoRevitApp.AddIdleAction(() => Update());
+#endif
}
[JsonConstructor]
@@ -61,17 +67,19 @@ public SiteLocation(IEnumerable inPorts, IEnumerable outPo
ArgumentLacing = LacingStrategy.Disabled;
- DynamoRevitApp.EventHandlerProxy.DocumentOpened += model_RevitDocumentChanged;
+ RevitServices.EventHandler.EventHandlerProxy.Instance.DocumentOpened += model_RevitDocumentChanged;
RevitServicesUpdater.Instance.ElementsUpdated += RevitServicesUpdater_ElementsUpdated;
+#if !DESIGN_AUTOMATION
DynamoRevitApp.AddIdleAction(() => Update());
+#endif
}
#region public methods
public override void Dispose()
{
- DynamoRevitApp.EventHandlerProxy.DocumentOpened -= model_RevitDocumentChanged;
+ RevitServices.EventHandler.EventHandlerProxy.Instance.DocumentOpened -= model_RevitDocumentChanged;
RevitServicesUpdater.Instance.ElementsUpdated -= RevitServicesUpdater_ElementsUpdated;
base.Dispose();
}
diff --git a/src/Libraries/RevitNodesUI/SunPath.cs b/src/Libraries/RevitNodesUI/SunPath.cs
index eee3f8fd9c..82d1dfb2be 100644
--- a/src/Libraries/RevitNodesUI/SunPath.cs
+++ b/src/Libraries/RevitNodesUI/SunPath.cs
@@ -2,9 +2,9 @@
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
-
+#if !DESIGN_AUTOMATION
using Autodesk.Revit.UI.Events;
-
+#endif
using Dynamo.Applications;
using Dynamo.Applications.Models;
using Dynamo.Graph.Nodes;
@@ -32,33 +32,38 @@ public SunSettings()
RegisterAllPorts();
RevitServicesUpdater.Instance.ElementsUpdated += Updater_ElementsUpdated;
- DynamoRevitApp.EventHandlerProxy.ViewActivated += CurrentUIApplication_ViewActivated;
+#if !DESIGN_AUTOMATION
+ RevitServices.EventHandler.EventHandlerProxy.Instance.ViewActivated += CurrentUIApplication_ViewActivated;
DynamoRevitApp.AddIdleAction(() => CurrentUIApplicationOnViewActivated());
+#endif
}
[JsonConstructor]
public SunSettings(IEnumerable inPorts, IEnumerable outPorts) : base(inPorts, outPorts)
{
RevitServicesUpdater.Instance.ElementsUpdated += Updater_ElementsUpdated;
- DynamoRevitApp.EventHandlerProxy.ViewActivated += CurrentUIApplication_ViewActivated;
-
+#if !DESIGN_AUTOMATION
+ RevitServices.EventHandler.EventHandlerProxy.Instance.ViewActivated += CurrentUIApplication_ViewActivated;
DynamoRevitApp.AddIdleAction(() => CurrentUIApplicationOnViewActivated());
+#endif
}
public override void Dispose()
{
RevitServicesUpdater.Instance.ElementsUpdated -= Updater_ElementsUpdated;
- DynamoRevitApp.EventHandlerProxy.ViewActivated -= CurrentUIApplication_ViewActivated;
-
+#if !DESIGN_AUTOMATION
+ RevitServices.EventHandler.EventHandlerProxy.Instance.ViewActivated -= CurrentUIApplication_ViewActivated;
+#endif
base.Dispose();
}
+#if !DESIGN_AUTOMATION
private void CurrentUIApplication_ViewActivated(object sender, ViewActivatedEventArgs e)
{
CurrentUIApplicationOnViewActivated();
}
-
+#endif
private void CurrentUIApplicationOnViewActivated()
{
settingsID =
diff --git a/src/Libraries/RevitServices/Events/EventHandlerProxy.cs b/src/Libraries/RevitServices/Events/EventHandlerProxy.cs
index 424765351a..e80e72b116 100644
--- a/src/Libraries/RevitServices/Events/EventHandlerProxy.cs
+++ b/src/Libraries/RevitServices/Events/EventHandlerProxy.cs
@@ -1,6 +1,5 @@
using System;
using Autodesk.Revit.DB.Events;
-using Autodesk.Revit.UI.Events;
namespace RevitServices.EventHandler
{
@@ -8,13 +7,18 @@ namespace RevitServices.EventHandler
/// This is a event handler proxy class to serve as a proxy between the event publisher and
/// the event subscriber
///
+ [Obsolete("This class will be made internal")]
public class EventHandlerProxy
{
public event EventHandler DocumentOpened;
public event EventHandler DocumentClosing;
public event EventHandler DocumentClosed;
- public event EventHandler ViewActivating;
- public event EventHandler ViewActivated;
+#if !DESIGN_AUTOMATION
+ public event EventHandler ViewActivating;
+ public event EventHandler ViewActivated;
+#endif
+
+ internal static EventHandlerProxy Instance = new();
public void OnApplicationDocumentOpened(object sender, DocumentOpenedEventArgs args)
{
@@ -31,15 +35,17 @@ public void OnApplicationDocumentClosed(object sender, DocumentClosedEventArgs a
InvokeEventHandler(DocumentClosed, sender, args);
}
- public void OnApplicationViewActivating(object sender, ViewActivatingEventArgs args)
+#if !DESIGN_AUTOMATION
+ public void OnApplicationViewActivating(object sender, Autodesk.Revit.UI.Events.ViewActivatingEventArgs args)
{
InvokeEventHandler(ViewActivating, sender, args);
}
- public void OnApplicationViewActivated(object sender, ViewActivatedEventArgs args)
+ public void OnApplicationViewActivated(object sender, Autodesk.Revit.UI.Events.ViewActivatedEventArgs args)
{
InvokeEventHandler(ViewActivated, sender, args);
}
+#endif
private void InvokeEventHandler(EventHandler eventHandler, object sender, T args) where T: EventArgs
{
diff --git a/src/Libraries/RevitServices/Persistence/DocumentManager.cs b/src/Libraries/RevitServices/Persistence/DocumentManager.cs
index b92124e6a7..6c853e3cf6 100644
--- a/src/Libraries/RevitServices/Persistence/DocumentManager.cs
+++ b/src/Libraries/RevitServices/Persistence/DocumentManager.cs
@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.DB;
-using Autodesk.Revit.UI;
using RevitServices.Elements;
using RevitServices.Transactions;
@@ -116,6 +116,8 @@ public void HandleDocumentActivation(View revitView)
ActiveDocumentHashCode = revitView.Document.GetHashCode();
}
+ private Document currentDBDocument;
+
///
/// Provides the currently active DB document.
/// This is based on the CurrentUIDocument
@@ -123,8 +125,15 @@ public void HandleDocumentActivation(View revitView)
public Document CurrentDBDocument {
get
{
+#if !DESIGN_AUTOMATION
var c = CurrentUIDocument;
return c == null ? null : c.Document;
+#else
+ return currentDBDocument;
+#endif
+ }
+ set {
+ currentDBDocument = value;
}
}
@@ -143,17 +152,24 @@ public Document CurrentDBDocument {
///
public int ActiveDocumentHashCode { get; private set; }
+
+ ///
+ /// Provides the current Application
+ ///
+ internal Application CurrentApplication { get; set; }
+
+#if !DESIGN_AUTOMATION
///
/// Provides the currently active UI document.
/// This is the document to which Dynamo is bound.
///
- public UIDocument CurrentUIDocument {get; set; }
+ public Autodesk.Revit.UI.UIDocument CurrentUIDocument {get; set; }
///
/// Provides the current UIApplication
///
- public UIApplication CurrentUIApplication { get; set; }
-
+ public Autodesk.Revit.UI.UIApplication CurrentUIApplication { get; set; }
+#endif
///
/// Trigger a document regeneration in the idle context or without
/// depending on the state of the transaction manager.
@@ -171,5 +187,26 @@ public static void Regenerate()
Instance.CurrentDBDocument.Regenerate();
}
}
+
+ ///
+ /// Setup the CurrentDBDocument and CurrentApplication.
+ ///
+ ///
+ internal void PrepareForDesignAutomation(Application app)
+ {
+ if (app == null)
+ {
+ return;
+ }
+ CurrentApplication = app;
+ foreach (Document d in app.Documents)
+ {
+ if (!d.IsLinked)
+ {
+ CurrentDBDocument = d;
+ break;
+ }
+ }
+ }
}
}
diff --git a/src/Libraries/RevitServices/Properties/AssemblyInfo.cs b/src/Libraries/RevitServices/Properties/AssemblyInfo.cs
index fa60dc9887..a0d3de35aa 100644
--- a/src/Libraries/RevitServices/Properties/AssemblyInfo.cs
+++ b/src/Libraries/RevitServices/Properties/AssemblyInfo.cs
@@ -1,4 +1,5 @@
using System.Reflection;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
@@ -9,3 +10,7 @@
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("026be738-81b6-4a11-bc14-36ee3f718921")]
+[assembly: InternalsVisibleTo("DADynamoApp")]
+[assembly: InternalsVisibleTo("RevitNodes")]
+[assembly: InternalsVisibleTo("DSRevitNodesUI")]
+[assembly: InternalsVisibleTo("DynamoRevitDS")]
\ No newline at end of file
diff --git a/src/Libraries/RevitServices/RevitServices.csproj b/src/Libraries/RevitServices/RevitServices.csproj
index 0e1c032d73..15d4015a59 100644
--- a/src/Libraries/RevitServices/RevitServices.csproj
+++ b/src/Libraries/RevitServices/RevitServices.csproj
@@ -20,29 +20,10 @@ limitations under the License.
8.0.30703
false
-
true
true
-
- true
- full
- false
- TRACE;DEBUG
- prompt
- 4
- false
-
-
- full
- true
- TRACE
- prompt
- 4
- true
- false
-
$(REVITAPI)\RevitAPI.dll
@@ -75,6 +56,7 @@ limitations under the License.
+
diff --git a/test/Libraries/RevitIntegrationTests/DALoggerTests.cs b/test/Libraries/RevitIntegrationTests/DALoggerTests.cs
new file mode 100644
index 0000000000..4387568d48
--- /dev/null
+++ b/test/Libraries/RevitIntegrationTests/DALoggerTests.cs
@@ -0,0 +1,68 @@
+using System;
+using System.IO;
+using DADynamoApp;
+using NUnit.Framework;
+using RevitTestServices;
+using RTF.Framework;
+
+namespace RevitSystemTests
+{
+ [TestFixture]
+ class DALoggerTests : RevitSystemTestBase
+ {
+ private StringWriter capturedOutput;
+ private TextWriter originalOutput;
+
+ [SetUp]
+ public override void Setup()
+ {
+ base.Setup();
+ capturedOutput = new StringWriter();
+ originalOutput = Console.Out;
+ Console.SetOut(capturedOutput);
+ }
+
+ [TearDown]
+ public override void TearDown()
+ {
+ Console.SetOut(originalOutput);
+ capturedOutput?.Dispose();
+ base.TearDown();
+ }
+
+ // TODO: Refactor DAEntrypoint so that all post-model-startup logic lives in a separate
+ // internal DAApp class that accepts a DynamoModel in its constructor. DAEntrypoint would
+ // just create the model and hand it to new DAApp(model). This test could then do:
+ // var app = new DAApp(ViewModel.Model);
+ // app.SetupProfilingHandlers();
+ // ...which tests the actual DA code path without needing to create a DAEntrypoint at all,
+ // and makes it straightforward to test graph running too (pass a work item folder).
+
+ ///
+ /// Verifies that DAEntrypoint.SetupProfilingHandlers wires up node execution events that
+ /// call DALogger.SerializeNodeOutputs and write profiling output to stdout.
+ ///
+ [Test]
+ [TestModel(@".\empty.rfa")]
+ public void SetupProfilingHandlers_WritesNodeOutputToStdout()
+ {
+ // Use the actual production method — SetupProfilingHandlers subscribes to WorkspaceOpened
+ // and wires all the profiling/serialization handlers on the model we already have.
+ var entrypoint = new DAEntrypoint();
+ entrypoint.SetupProfilingHandlers(Model);
+
+ string dynPath = Path.GetFullPath(Path.Combine(workingDirectory, @".\Core\SanityCheck.dyn"));
+ ViewModel.OpenCommand.Execute(dynPath);
+ RunCurrentModel();
+
+ var output = capturedOutput.ToString();
+
+ // Profiling start/end lines must appear
+ StringAssert.Contains("Node Point.ByCoordinates started execution.", output);
+ StringAssert.Contains("Node Point.ByCoordinates finished execution.", output);
+
+ // DALogger.SerializeNodeOutputs must have returned something for the Point node
+ StringAssert.Contains("Node Point.ByCoordinates outputs:", output);
+ }
+ }
+}
diff --git a/test/Libraries/RevitIntegrationTests/RevitSystemTests.csproj b/test/Libraries/RevitIntegrationTests/RevitSystemTests.csproj
index 9fa6b44a42..8a8ef3ddaa 100644
--- a/test/Libraries/RevitIntegrationTests/RevitSystemTests.csproj
+++ b/test/Libraries/RevitIntegrationTests/RevitSystemTests.csproj
@@ -54,6 +54,7 @@
+
diff --git a/test/Libraries/RevitNodesTests/Elements/DirectShapeTests.cs b/test/Libraries/RevitNodesTests/Elements/DirectShapeTests.cs
index 3353d12176..ce95e3d909 100644
--- a/test/Libraries/RevitNodesTests/Elements/DirectShapeTests.cs
+++ b/test/Libraries/RevitNodesTests/Elements/DirectShapeTests.cs
@@ -54,7 +54,7 @@ private int CheckNumTriangles(DirectShape ds)
private static DirectShape CreateDirectShapeFromQuadPoints(Point p1, Point p2, Point p3, Point p4)
{
var index = IndexGroup.ByIndices(0, 1, 2, 3);
- var mesh = Mesh.ByPointsIndexGroups(new List() { p1, p2, p3, p4 }, new List() { index });
+ var mesh = Mesh.ByPointsFaceIndices(new List() { p1, p2, p3, p4 }, new List() { index });
var mat = DocumentManager.Instance.ElementsOfType().First();
var ds = DirectShape.ByMesh(mesh, Category.ByName("OST_GenericModel"), Material.ByName(mat.Name), "a mesh");
mesh.Dispose();
@@ -191,7 +191,7 @@ public void ByMeshNameCategoryMaterial_ValidInput()
var index1 = IndexGroup.ByIndices(0,1,2);
- var mesh= Mesh.ByPointsIndexGroups(new List() { p1, p2, p3 }, new List() { index1 });
+ var mesh= Mesh.ByPointsFaceIndices(new List() { p1, p2, p3 }, new List() { index1 });
var mat = DocumentManager.Instance.ElementsOfType().First();
var ds = DirectShape.ByMesh(mesh, Category.ByName("OST_GenericModel"), Material.ByName(mat.Name), "a mesh");
@@ -220,7 +220,7 @@ public void ByMeshAndBySurfaceBothLocatedSameMetric()
var index1 = IndexGroup.ByIndices(0, 1, 2);
- var mesh = Mesh.ByPointsIndexGroups(new List() { p1, p2, p3 }, new List() { index1 });
+ var mesh = Mesh.ByPointsFaceIndices(new List() { p1, p2, p3 }, new List() { index1 });
var surf = Surface.ByPerimeterPoints(new List() { p1, p2, p3 });
var mat = DocumentManager.Instance.ElementsOfType().First();
diff --git a/test/Libraries/RevitServicesTests/RevitServicesTests.csproj b/test/Libraries/RevitServicesTests/RevitServicesTests.csproj
index ea12e9767f..79fdc90c51 100644
--- a/test/Libraries/RevitServicesTests/RevitServicesTests.csproj
+++ b/test/Libraries/RevitServicesTests/RevitServicesTests.csproj
@@ -25,25 +25,6 @@ limitations under the License.
None
-
- true
- full
- false
- DEBUG;TRACE
- prompt
- 4
- AnyCPU
- false
-
-
- pdbonly
- true
- TRACE
- prompt
- 4
- true
- false
-
$(REVITAPI)\RevitAPI.dll
diff --git a/test/Libraries/RevitTestServices/RevitNodeTestBase.cs b/test/Libraries/RevitTestServices/RevitNodeTestBase.cs
index 1be498945d..360078c97f 100644
--- a/test/Libraries/RevitTestServices/RevitNodeTestBase.cs
+++ b/test/Libraries/RevitTestServices/RevitNodeTestBase.cs
@@ -43,7 +43,8 @@ public override void Setup()
protected override TestSessionConfiguration GetTestSessionConfiguration()
{
var asmLocation = AppDomain.CurrentDomain.BaseDirectory;
- return new TestSessionConfiguration(Dynamo.Applications.DynamoRevitApp.DynamoCorePath, DynamoRevit.PreloadAsmFromRevit());
+ Version version = ASMPrealoaderUtils.PreloadAsmFromRevit(DynamoRevitApp.ControlledApplication.SharedComponentsLocation, DynamoRevitApp.DynamoCorePath);
+ return new TestSessionConfiguration(Dynamo.Applications.DynamoRevitApp.DynamoCorePath, version);
}
private static void SetupTransactionManager()
diff --git a/test/Libraries/RevitTestServices/RevitSystemTestBase.cs b/test/Libraries/RevitTestServices/RevitSystemTestBase.cs
index 15b172b56c..112daf0437 100644
--- a/test/Libraries/RevitTestServices/RevitSystemTestBase.cs
+++ b/test/Libraries/RevitTestServices/RevitSystemTestBase.cs
@@ -270,13 +270,13 @@ protected override void StartDynamo(TestSessionConfiguration testConfig)
// Init DynamoTestPath to get DynamoSettings.xml which under user data folder
PreferenceSettings.DynamoTestPath = string.Empty;
//preload ASM and instruct dynamo to load that version of libG.
- var requestedLibGVersion = DynamoRevit.PreloadAsmFromRevit();
+ var requestedLibGVersion = ASMPrealoaderUtils.PreloadAsmFromRevit(DynamoRevitApp.ControlledApplication.SharedComponentsLocation, testConfig.DynamoCorePath);
DynamoRevit.RevitDynamoModel = RevitDynamoModel.Start(
new RevitDynamoModel.RevitStartConfiguration()
{
StartInTestMode = true,
- GeometryFactoryPath = DynamoRevit.GetGeometryFactoryPath(testConfig.DynamoCorePath, requestedLibGVersion),
+ GeometryFactoryPath = ASMPrealoaderUtils.GetGeometryFactoryPath(testConfig.DynamoCorePath, requestedLibGVersion),
DynamoCorePath = testConfig.DynamoCorePath,
PathResolver = revitTestPathResolver,
Context = DynamoRevit.GetRevitContext(commandData),