Get the custom node package location in python script node

Hi,

I have a custom node that I published as a local package. When publishing I added an external exe file to the package, I’m launching this exe from within a Python Script nod in my custom node, it gets saved in the “extra” subfolder of the package’s folder.

When I hard-code the exe file path in the script it works fine, but I need to grab the relative path of the exe starting from the .dyf file location in order to prepare this package for distribution.

I couldn’t find a way to do that, the python function os.getcwd() returns the Revit.exe folder, and the internal python script has no __file__ attribute to count on.

Any suggestions are greatly appreciated!

Thanks!

You can read the Dynamo instance’s package paths, and then comb them for your package name, and append the extras path from there. It’s slow as heck though, and not very much fun.

Better still, if you have an exe then why not move to C# which can allow you to get the directory of the executing assembly? I believe this is how @john_pierson handles it in Rhythm. Alternatively you could build an installer instead and use that to ensure the exe is at a known location.

Depending on the version, the dynamo api can do this.

Is this package for revit or another vertical?

Here are 2 solutions for finding the user packages directory

curious to know if there are other methods

method 1 (brute force)


import sys
import clr
import System

try:
	clr.AddReference('System')
	from System.Diagnostics import Process
# for Net Core
except:
	clr.AddReference('System.Diagnostics.Process')
	from System.Diagnostics import Process

clr.AddReference("System.Reflection")
from System.Reflection import BindingFlags

from System.Reflection import Assembly
dynamo = Assembly.Load('DynamoCore')
dynamo_version = dynamo.GetName().Version
print('dynamo_version', dynamo_version)

appDataDirectory = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData)

pocessName = Process.GetCurrentProcess().ProcessName

if pocessName == "DynamoSandbox" :
    if "Roaming" in appDataDirectory :
        user_packagesDirectory = appDataDirectory + "\\Dynamo\\Dynamo Core\\{}.{}\\packages\\".format(dynamo_version.Major, dynamo_version.Minor)
        
    else:
        user_packagesDirectory = appDataDirectory + "\\Roaming\\Dynamo\\Dynamo Core\\{}.{}\\packages\\".format(dynamo_version.Major, dynamo_version.Minor)
# Dynamo Revit
else:
    if "Roaming" in appDataDirectory :
        user_packagesDirectory = appDataDirectory + "\\Dynamo\\Dynamo Revit\\{}.{}\\packages\\".format(dynamo_version.Major, dynamo_version.Minor)
        
    else:
        user_packagesDirectory = appDataDirectory + "\\Roaming\\Dynamo\\Dynamo Revit\\{}.{}\\packages\\".format(dynamo_version.Major, dynamo_version.Minor)
        
        
OUT = user_packagesDirectory,

method 2 (with DynamoRevit API)

import sys
import clr
import System
appDataDirectory = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData)
clr.AddReference('DynamoRevitDS')
import Dynamo 

#access to the current Dynamo instance and workspace
dynamoRevit = Dynamo.Applications.DynamoRevit()
engine = dynamoRevit.RevitDynamoModel.EngineController
currentWorkspace = dynamoRevit.RevitDynamoModel.CurrentWorkspace
model = dynamoRevit.RevitDynamoModel

pref = model.PreferenceSettings

user_packagesDirectory = next((x + "\\packages\\" for x in pref.CustomPackageFolders if x.startswith(appDataDirectory)), None)

OUT = user_packagesDirectory,
2 Likes