Is there no good way to get document paths to the local Desktop connector? we could use a better way to properly get these paths to the Current ACC project, and the current document path (with subfolders)
Tracking back through getting Desktop Connector (DC) paths - ended up in a Zero Touch(Below) but might drop back to Python if we’re just parsing the DC path. I want our tools to write out JSON files when team run the apps to track what happened, when, and how much they are being used (Net to the RVT file, the project and a central location- maybe a SQL DB).
The top output of the ZTN is the complete DC Path to the model less the RVT extension to quick-tac on the extension and write out the fie.
//Revit API namespaces
using Autodesk.Revit.DB;
using Autodesk.Revit.ApplicationServices;
using Autodesk.DesignScript.Runtime;
//using RevitServices.Persistence;
//using System;
using System.Collections.Generic;
using System.Linq;
namespace BETA
{
public static partial class Parameters
{
// Expose this method to Dynamo with named return values
[IsVisibleInDynamoLibrary(true)]
[MultiReturn(new[] { "SharedParamMatch", "SharedParamMismatch", "ProjectParam", "Debug" })]
public static Dictionary<string, List<string>> ParametersByType(object docInput, string sharedParamFilePath)
{
// Lists to store categorized parameter names
var sharedParamMatch = new List<string>(); // Parameters found in both Revit and shared param file
var sharedParamMismatch = new List<string>(); // Parameters only in shared param file
var projectParam = new List<string>(); // Parameters only in Revit project
var debug = new List<string>(); // Step-by-step debug messages
// Convert input to Revit document
Document doc = RevitDocHelper.GetDocument(docInput);
if (doc == null)
{
// Early exit if the document is invalid
debug.Add("Invalid Revit document");
return new Dictionary<string, List<string>> {
{ "SharedParamMatch", sharedParamMatch },
{ "SharedParamMismatch", sharedParamMismatch },
{ "ProjectParam", projectParam },
{ "Debug", debug }
};
}
// Check for a valid shared parameter file path
if (string.IsNullOrWhiteSpace(sharedParamFilePath))
{
debug.Add("Shared parameter file path is null or empty");
return new Dictionary<string, List<string>> {
{ "SharedParamMatch", sharedParamMatch },
{ "SharedParamMismatch", sharedParamMismatch },
{ "ProjectParam", projectParam },
{ "Debug", debug }
};
}
// Load the shared parameter file
Application app = doc.Application;
app.SharedParametersFilename = sharedParamFilePath;
DefinitionFile defFile = app.OpenSharedParameterFile();
if (defFile == null)
{
debug.Add("Failed to load shared parameter file at path");
return new Dictionary<string, List<string>> {
{ "SharedParamMatch", sharedParamMatch },
{ "SharedParamMismatch", sharedParamMismatch },
{ "ProjectParam", projectParam },
{ "Debug", debug }
};
}
// Set of lowercased shared parameter names for fast lookup
var sharedParamNamesSet = new HashSet<string>();
// Dictionary to retain original casing for later display
var sharedParamNamesAll = new Dictionary<string, string>(); // key = lowercased name, value = original name
// Iterate through all shared parameters in all groups
foreach (var def in defFile.Groups.Cast<DefinitionGroup>().SelectMany(g => g.Definitions.Cast<Definition>()).OfType<ExternalDefinition>())
{
string name = def.Name?.Trim() ?? "";
string lower = name.ToLowerInvariant();
if (!string.IsNullOrEmpty(lower))
{
sharedParamNamesSet.Add(lower);
if (!sharedParamNamesAll.ContainsKey(lower))
sharedParamNamesAll[lower] = name;
}
}
debug.Add("Loaded " + sharedParamNamesAll.Count + " shared parameters");
// Set to track shared parameters actually found in project
var foundSharedParams = new HashSet<string>();
// Track all project parameters for fallback comparison
var allProjectParamNames = new HashSet<string>();
// Revit's project parameter bindings
BindingMap map = doc.ParameterBindings;
DefinitionBindingMapIterator iter = map.ForwardIterator();
iter.Reset();
// First pass to check which shared params exist in project
while (iter.MoveNext())
{
Definition def = iter.Key;
string name = def?.Name?.Trim() ?? "Unnamed";
string lowerName = name.ToLowerInvariant();
// Determine binding type (Instance or Type)
string bindingType = iter.Current is InstanceBinding ? "Instance" :
iter.Current is TypeBinding ? "Type" : "Unknown";
// Add to full set of project param names
allProjectParamNames.Add(lowerName);
// If parameter matches a shared param (by lowercase name)
if (sharedParamNamesSet.Contains(lowerName))
{
sharedParamMatch.Add(name); // Add to match list (original name)
foundSharedParams.Add(lowerName); // Track as found
debug.Add("Shared match " + name + " " + bindingType); // Log match
}
}
// Find shared parameters that are *not* found in project
foreach (var kvp in sharedParamNamesAll)
{
if (!foundSharedParams.Contains(kvp.Key))
{
sharedParamMismatch.Add(kvp.Value); // Use original casing
debug.Add("Shared mismatch " + kvp.Value);
}
}
// Second pass to find parameters that are in project but not shared
iter.Reset();
while (iter.MoveNext())
{
Definition def = iter.Key;
string name = def?.Name?.Trim() ?? "Unnamed";
string lowerName = name.ToLowerInvariant();
// Add to projectParam only if not already matched or found in shared param list
if (!foundSharedParams.Contains(lowerName) && !sharedParamNamesSet.Contains(lowerName))
{
projectParam.Add(name);
debug.Add("Project only " + name);
}
}
// Return all three categories along with debug log
return new Dictionary<string, List<string>> {
{ "SharedParamMatch", sharedParamMatch },
{ "SharedParamMismatch", sharedParamMismatch },
{ "ProjectParam", projectParam },
{ "Debug", debug }
};
}
}
}