Skip to content

Conversation

@RobertGlobant20
Copy link
Contributor

Purpose

With this fix now the Sample files located in Dynamo\doc\distrib\Samples will be copied when building the solution to DynamoCore\Samples, so if we try to open the Default Samples folder from DynamoHome this new path will be opened by default.
Note: I'm still pending in testing this change in Dynamo Revit.

Declarations

Check these if you believe they are true

Release Notes

Updating the default path used for Samples when using DynamoSandbox

Reviewers

@QilongTang @zeusongit @johnpierson

FYIs

@achintyabhat

With this fix not the Sample files located in Dynamo\doc\distrib\Samples will be copied during building the solution to DynamoCore\Samples, so if we try to open the Default Samples folder from Dynamo menu or DynamoHome this new path will be opened.
Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the ticket for this pull request: https://jira.autodesk.com/browse/DYN-9244

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes the default samples path for DynamoSandbox by copying sample files from the documentation directory to a local Samples folder during build and updating the path resolution logic.

  • Changes the common data directory path from using system's CommonApplicationData to the DynamoCore assembly location with a "Samples" subfolder
  • Adds build step to copy sample files from extern/doc/distrib/Samples to the output Samples directory
  • Removes dependency on GetCommonDataFolder method and pathResolver for samples location

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/DynamoCoreWpf/DynamoCoreWpf.csproj Adds MSBuild target to copy sample files during build process
src/DynamoCore/Configuration/PathManager.cs Updates samples directory resolution to use local assembly path instead of system CommonApplicationData
src/DynamoCore/Configuration/Configurations.cs Adds SamplesAsString constant for folder name consistency

@RobertGlobant20
Copy link
Contributor Author

This is a GIF showing the expected behavior:
DynamoSandbox_dEj03MEM6z

@QilongTang
Copy link
Contributor

Thank you @RobertGlobant20 I also committed the suggestion by Copilot. Waiting for PR checks

var dynamoCorePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
// Common directories.
commonDataDir = GetCommonDataFolder();
commonDataDir = Path.Combine(dynamoCorePath, Configurations.SamplesAsString);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What else is this commonDataDir used for? Is changing this value completely going to break other features?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, @QilongTang!

@RobertGlobant20 since the commonDataDir is the basis on which samplesDirectory and defaultTemplatesDirectory below are derived, sending commonDataDir with "\Samples" suffix into GetTemplateFolder() below does not sound correct to me:

commonDataDir = "%UserProfile%\Documents\dev\Dynamo\bin\AnyCPU\Debug\Samples";

// Get nested sample path?
samplesDirectory = GetSamplesFolder(commonDataDir);

// Get template path from sample path?
defaultTemplatesDirectory = GetTemplateFolder(commonDataDir);

The reason it still returns the correct (or rather, default) samplesDirectory and defaultTemplatesDirectory is because the malformed directory self-corrected to this value because of the non-existence "\Samples" directory:

%UserProfile%\Documents\dev\Dynamo\bin\AnyCPU\Debug\templates\en-US

In addition to that, commonDataDir is exposed through PathManager.CommonDataDirectory property and is referenced by DynamoCore and DynamoCoreWpf alike. As it stands the path is set to %UserProfile%\Documents\dev\Dynamo\bin\AnyCPU\Debug\Samples, which might not be desirable.

I am not up-to-date with all the discussions, but if we need the samples alongside DynamoCore.dll, the following would suffice:

commonDataDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@QilongTang to your question I'm still checking if it will affect the ExtensionManager and the functionality of loading the DynamoSettings.xml from other location but I'm still testing/debugging the changes in Revit to see how it will affect.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@benglin to your comments, I made a mistake about including "samples" as part of commonDataDir, I alredy fixed the problem in the next commit: 6149d10
But I'm still trying to test how my change behaves in Revit, I will let you know the results.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For sure, @RobertGlobant20, thanks again for fixing this 👍

Copy link
Contributor

@benglin benglin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @RobertGlobant20, hang in there, we're almost done! 🙂

I've debugged this code and compared it with 3.6 (which I believe predates the program-data work), and I found something interesting.

User Data a.k.a. AppData

The new PathManager behaves exactly as it did in 3.6 -- excellent work there!

| PathManager Property     | 3.6                                                 | 4.0                                                 |
| ------------------------ | --------------------------------------------------- | --------------------------------------------------- |
| BackupDirectory          | %AppData%\Dynamo\Dynamo Core\backup                 | %AppData%\Dynamo\Dynamo Core\backup                 |
| DefaultUserDefinitions   | %AppData%\Dynamo\Dynamo Core\3.6\definitions        | %AppData%\Dynamo\Dynamo Core\4.0\definitions        |
| DefaultPackagesDirectory | %AppData%\Dynamo\Dynamo Core\3.6\packages           | %AppData%\Dynamo\Dynamo Core\4.0\packages           |
| LogDirectory             | %AppData%\Dynamo\Dynamo Core\3.6\Logs               | %AppData%\Dynamo\Dynamo Core\4.0\Logs               |
| UserDataDirectory        | %AppData%\Dynamo\Dynamo Core\3.6                    | %AppData%\Dynamo\Dynamo Core\4.0                    |
| PreferenceFilePath       | %AppData%\Dynamo\Dynamo Core\3.6\DynamoSettings.xml | %AppData%\Dynamo\Dynamo Core\4.0\DynamoSettings.xml |
| PythonTemplateFilePath   | %AppData%\Dynamo\Dynamo Core\3.6\PythonTemplate.py  | %AppData%\Dynamo\Dynamo Core\4.0\PythonTemplate.py  |

Common Data a.k.a. ProgramData

This is where things diverge slightly. Looking at what we have in PathManager, it appears we're close to achieving our goal. The remaining codebase will need to align with PathManager as the source of truth (for example, the Help > Samples menu item should respect the SamplesDirectory value provided by the PathManager singleton).

| PathManager Property      | 3.6                                              | 4.0                                                       |
| ------------------------- | ------------------------------------------------ | --------------------------------------------------------- |
| CommonDataDirectory       | %ProgramData%\Dynamo\Dynamo Core\3.6             | %UserProfile%\dev\Dynamo\bin\AnyCPU\Debug\Samples         |
| CommonDefinitions         | %ProgramData%\Dynamo\Dynamo Core\3.6\definitions | N/A                                                       |
| CommonPackageDirectory    | %ProgramData%\Dynamo\Dynamo Core\3.6\packages    | N/A                                                       |
| DefaultTemplatesDirectory | %ProgramData%\Dynamo\Dynamo Core\templates\en-US | %UserProfile%\dev\Dynamo\bin\AnyCPU\Debug\templates\en-US |
| SamplesDirectory          | %ProgramData%\Dynamo\Dynamo Core\samples\en-US   | %UserProfile%\dev\Dynamo\bin\AnyCPU\Debug\samples\en-US   |
| DynamoCoreDirectory       | %UserProfile%\dev\Dynamo\bin\AnyCPU\Debug        | %UserProfile%\dev\Dynamo\bin\AnyCPU\Debug                 |

There are several categories of items to address. Since I'm not up-to-date on recent architectural decisions, please correct me if my understanding is off base.

CommonDefinitions and CommonPackageDirectory

These properties are omitted in PathManager 4.0. If there was a deliberate decision to consolidate these with their user data counterparts (DefaultUserDefinitions, DefaultPackagesDirectory), that makes sense. If not, we should discuss this further.

DynamoCoreDirectory vs. CommonDataDirectory

DynamoCoreDirectory is consistently set to the directory containing DynamoCore.dll, which is correct. What I'd like to highlight is the CommonDataDirectory value, which appears to have shifted from a centralized data location to point to the same DynamoCore.dll directory (assuming we remove the "\Samples" suffix):

| PathManager Property | 3.6                                       | 4.0                                       |
| -------------------- | ----------------------------------------- | ----------------------------------------- |
| DynamoCoreDirectory  | %UserProfile%\dev\Dynamo\bin\AnyCPU\Debug | %UserProfile%\dev\Dynamo\bin\AnyCPU\Debug |
| CommonDataDirectory  | %ProgramData%\Dynamo\Dynamo Core\3.6      | %UserProfile%\dev\Dynamo\bin\AnyCPU\Debug |

Both ViewExtensionLoader and ExtensionLoader use CommonDataDirectory to figure out which extensions need certification verification. Now that it points to the DynamoCore.dll directory, any extensions there will get their signatures checked -- which is great.

This does make me wonder about how extensions get installed though (well, apart from built-in extensions, of course). If this becomes the main (or only) place we load extensions from, they'd need to be installed alongside host apps like Revit, which requires elevated permissions. Are we keeping something like the old %ProgramData%\Dynamo\Dynamo Core\3.6 path (by moving it under %AppData%) for user-installable extensions? Or has the whole approach changed?

I might be behind on how extension loading works these days, so feel free to correct me if things have moved in a different direction 🙂

var dynamoCorePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
// Common directories.
commonDataDir = GetCommonDataFolder();
commonDataDir = Path.Combine(dynamoCorePath, Configurations.SamplesAsString);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, @QilongTang!

@RobertGlobant20 since the commonDataDir is the basis on which samplesDirectory and defaultTemplatesDirectory below are derived, sending commonDataDir with "\Samples" suffix into GetTemplateFolder() below does not sound correct to me:

commonDataDir = "%UserProfile%\Documents\dev\Dynamo\bin\AnyCPU\Debug\Samples";

// Get nested sample path?
samplesDirectory = GetSamplesFolder(commonDataDir);

// Get template path from sample path?
defaultTemplatesDirectory = GetTemplateFolder(commonDataDir);

The reason it still returns the correct (or rather, default) samplesDirectory and defaultTemplatesDirectory is because the malformed directory self-corrected to this value because of the non-existence "\Samples" directory:

%UserProfile%\Documents\dev\Dynamo\bin\AnyCPU\Debug\templates\en-US

In addition to that, commonDataDir is exposed through PathManager.CommonDataDirectory property and is referenced by DynamoCore and DynamoCoreWpf alike. As it stands the path is set to %UserProfile%\Documents\dev\Dynamo\bin\AnyCPU\Debug\Samples, which might not be desirable.

I am not up-to-date with all the discussions, but if we need the samples alongside DynamoCore.dll, the following would suffice:

commonDataDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

Removing the const string SamplesDirectoryName and const string TemplateDirectoryName so and replace them by the ones defined in Configurations.
@RobertGlobant20
Copy link
Contributor Author

Hi @RobertGlobant20, hang in there, we're almost done! 🙂

I've debugged this code and compared it with 3.6 (which I believe predates the program-data work), and I found something interesting.

User Data a.k.a. AppData

The new PathManager behaves exactly as it did in 3.6 -- excellent work there!

| PathManager Property     | 3.6                                                 | 4.0                                                 |
| ------------------------ | --------------------------------------------------- | --------------------------------------------------- |
| BackupDirectory          | %AppData%\Dynamo\Dynamo Core\backup                 | %AppData%\Dynamo\Dynamo Core\backup                 |
| DefaultUserDefinitions   | %AppData%\Dynamo\Dynamo Core\3.6\definitions        | %AppData%\Dynamo\Dynamo Core\4.0\definitions        |
| DefaultPackagesDirectory | %AppData%\Dynamo\Dynamo Core\3.6\packages           | %AppData%\Dynamo\Dynamo Core\4.0\packages           |
| LogDirectory             | %AppData%\Dynamo\Dynamo Core\3.6\Logs               | %AppData%\Dynamo\Dynamo Core\4.0\Logs               |
| UserDataDirectory        | %AppData%\Dynamo\Dynamo Core\3.6                    | %AppData%\Dynamo\Dynamo Core\4.0                    |
| PreferenceFilePath       | %AppData%\Dynamo\Dynamo Core\3.6\DynamoSettings.xml | %AppData%\Dynamo\Dynamo Core\4.0\DynamoSettings.xml |
| PythonTemplateFilePath   | %AppData%\Dynamo\Dynamo Core\3.6\PythonTemplate.py  | %AppData%\Dynamo\Dynamo Core\4.0\PythonTemplate.py  |

Common Data a.k.a. ProgramData

This is where things diverge slightly. Looking at what we have in PathManager, it appears we're close to achieving our goal. The remaining codebase will need to align with PathManager as the source of truth (for example, the Help > Samples menu item should respect the SamplesDirectory value provided by the PathManager singleton).

| PathManager Property      | 3.6                                              | 4.0                                                       |
| ------------------------- | ------------------------------------------------ | --------------------------------------------------------- |
| CommonDataDirectory       | %ProgramData%\Dynamo\Dynamo Core\3.6             | %UserProfile%\dev\Dynamo\bin\AnyCPU\Debug\Samples         |
| CommonDefinitions         | %ProgramData%\Dynamo\Dynamo Core\3.6\definitions | N/A                                                       |
| CommonPackageDirectory    | %ProgramData%\Dynamo\Dynamo Core\3.6\packages    | N/A                                                       |
| DefaultTemplatesDirectory | %ProgramData%\Dynamo\Dynamo Core\templates\en-US | %UserProfile%\dev\Dynamo\bin\AnyCPU\Debug\templates\en-US |
| SamplesDirectory          | %ProgramData%\Dynamo\Dynamo Core\samples\en-US   | %UserProfile%\dev\Dynamo\bin\AnyCPU\Debug\samples\en-US   |
| DynamoCoreDirectory       | %UserProfile%\dev\Dynamo\bin\AnyCPU\Debug        | %UserProfile%\dev\Dynamo\bin\AnyCPU\Debug                 |

There are several categories of items to address. Since I'm not up-to-date on recent architectural decisions, please correct me if my understanding is off base.

CommonDefinitions and CommonPackageDirectory

These properties are omitted in PathManager 4.0. If there was a deliberate decision to consolidate these with their user data counterparts (DefaultUserDefinitions, DefaultPackagesDirectory), that makes sense. If not, we should discuss this further.

DynamoCoreDirectory vs. CommonDataDirectory

DynamoCoreDirectory is consistently set to the directory containing DynamoCore.dll, which is correct. What I'd like to highlight is the CommonDataDirectory value, which appears to have shifted from a centralized data location to point to the same DynamoCore.dll directory (assuming we remove the "\Samples" suffix):

| PathManager Property | 3.6                                       | 4.0                                       |
| -------------------- | ----------------------------------------- | ----------------------------------------- |
| DynamoCoreDirectory  | %UserProfile%\dev\Dynamo\bin\AnyCPU\Debug | %UserProfile%\dev\Dynamo\bin\AnyCPU\Debug |
| CommonDataDirectory  | %ProgramData%\Dynamo\Dynamo Core\3.6      | %UserProfile%\dev\Dynamo\bin\AnyCPU\Debug |

Both ViewExtensionLoader and ExtensionLoader use CommonDataDirectory to figure out which extensions need certification verification. Now that it points to the DynamoCore.dll directory, any extensions there will get their signatures checked -- which is great.

This does make me wonder about how extensions get installed though (well, apart from built-in extensions, of course). If this becomes the main (or only) place we load extensions from, they'd need to be installed alongside host apps like Revit, which requires elevated permissions. Are we keeping something like the old %ProgramData%\Dynamo\Dynamo Core\3.6 path (by moving it under %AppData%) for user-installable extensions? Or has the whole approach changed?

I might be behind on how extension loading works these days, so feel free to correct me if things have moved in a different direction 🙂
@benglin about this comments:

CommonDefinitions and CommonPackageDirectory
We are not supporting to load packages/definitions located in %ProgramData% path (@QilongTang please confirm that this is the expected behavior), now we only will be loading packages/definitions located in C:\Users\<user>\AppData\Roaming\Dynamo\Dynamo Core\4.0

DynamoCoreDirectory vs. CommonDataDirectory
This is a little confusing due that now that we are not putting stuff in % ProgramData % then there is not point in having the CommonDataDirectory property (because we won't have a folder that will be shared for all the users, previously we were considering ProgramFiles but the problem is that Dynamo needs admin permissions for writing on that folder so we discarded that option).
About the Extensions, I'm still checking if it will be affected.

@benglin
Copy link
Contributor

benglin commented Oct 8, 2025

Hi @RobertGlobant20, thanks for the details.

CommonDefinitions and CommonPackageDirectory

Perfect. The removal of these properties aligns with the goal of moving away from %ProgramData% to %AppData%. We're now supporting only per-user packages and definitions, which simplifies decision-making significantly.

DynamoCoreDirectory vs. CommonDataDirectory

Since extensions will now only be found next to DynamoCore.dll, CommonDataDirectory essentially duplicates DynamoCoreDirectory. I'd suggest removing CommonDataDirectory entirely for clarity -- there's no longer a separate "common" location.

For third-party extensions, they'll be installed as packages through Package Manager (please correct me if I'm wrong) into DefaultPackagesDirectory (%AppData%\Dynamo\Dynamo Core\3.6\packages). With CommonDataDirectory removed, we should redirect the DirectoriesToVerifyCertificates for both ExtensionLoader and ViewExtensionLoader to point to DefaultPackagesDirectory instead.

Quick question: Are we currently verifying certificates for DLLs loaded from DefaultPackagesDirectory? I don't see this being done in version 3.6.

previously we were considering "Program Files"...

Right, %ProgramFiles% has the same elevated permission requirements as %ProgramData%, so that doesn't solve our problem.

Based on your changes, CommonDataDirectory now points to these locations (which are the same as DynamoCoreDirectory):

Revit:   %ProgramFiles%\Autodesk\Revit 2027\AddIns\DynamoForRevit\
Sandbox: C:\Some\random\path\DynamoCoreRuntime4.0.0\

Given what we now know, my recommendation is to remove CommonDataDirectory and ensure DefaultPackagesDirectory is included in the certificate verification paths for both loaders.

This approach should give us a cleaner, more straightforward way to reason about our paths in Dynamo. Let me know what you find after making these changes!

P.S.: Could you sync to the latest codebase from master? This way we can ensure there are no other changes in master that might alter the final behavior. Thanks!

@QilongTang
Copy link
Contributor

QilongTang commented Oct 8, 2025

Maybe obsolete CommonDataDirectory if it's public

DirectoriesToVerifyCertificates was used to validate cert attached to packages installed to %ProgramData%, since we are moving away from it, it should be used to validate cert attached to packages installed to our Bult-In path.
https://autodesk.slack.com/archives/C08AMP1A7AB/p1759936098523479?thread_ts=1759877834.645319&cid=C08AMP1A7AB

@RobertGlobant20
Copy link
Contributor Author

RobertGlobant20 commented Oct 8, 2025

@benglin to your question:
Are we currently verifying certificates for DLLs loaded from DefaultPackagesDirectory? I don't see this being done in version 3.6.
As far as I remember there was code checking the certificates from the packages loaded from C:\ProgramData\Dynamo\Dynamo Core\4.0\packages, I never tested the case in which we don't have the certificates and the package was loaded. For the packages in the path C:\Users\<user>\AppData\Roaming\Dynamo\Dynamo Core\4.0\packages we were not checking certificates.

@RobertGlobant20
Copy link
Contributor Author

RobertGlobant20 commented Oct 8, 2025

@benglin ok, I will proceed to remove CommonDataDirectory and ensure DefaultPackagesDirectory is included in the certificate verification paths for both loaders.
But I anticipate that probably we need to think more about getting rid of CommonDataDirectory because also from hosts like Revit we are passing the variable pathResolver.CommonDataRootFolder which is used for setting CommonDataDirectory

With this fix is opening Samples/Templates in the next places:

DynamoSandbox
Samples -> Dynamo\bin\AnyCPU\Debug\Samples\en-US
Templates -> C:\ProgramData\Autodesk\Dynamo\Dynamo Core\templates\en-US

Dynamo on Revit 2027
Templates - C:\ProgramData\Autodesk\RVT 2027\Dynamo\templates\en-US
Samples - C:\ProgramData\Autodesk\RVR 2027\Dynamo\Samples\en-US
@QilongTang
Copy link
Contributor

@RobertGlobant20 PTAL the regressions reported for this PR

@benglin
Copy link
Contributor

benglin commented Oct 9, 2025

But I anticipate that probably we need to think more about getting rid of CommonDataDirectory because also from hosts like Revit we are passing the variable pathResolver.CommonDataRootFolder which is used for setting CommonDataDirectory

Ah yes @RobertGlobant20, I did not see this comment until now but I did mention something similar in your other PR #16528 that we may need to just mark it as obsolete but keep it around for compatibility reasons. Good one!

Edit: Also, I think it's worthwhile merging #16528 into this PR so the regressions can be fixed in one go, there are many moving parts if they are kept separated. Thanks!

Due that CommonDataDirectory was set to the DynamoCore directory it was adding this folder to DirectoriesToVerifyCertificates but DynamoCore/extensions and DynamoCore/viewExtensions don't have certificates so all the built-in extensions were not loaded.
After my fix I'm not adding entires to DirectoriesToVerifyCertificates so doesn't check for extensions with certificates in DynamoCore/extensions and DynamoCore/viewExtensions then are loaded correctly.
@RobertGlobant20
Copy link
Contributor Author

@RobertGlobant20 PTAL the regressions reported for this PR

Due that CommonDataDirectory was set to the DynamoCore directory it was adding this folder to DirectoriesToVerifyCertificates but DynamoCore/extensions and DynamoCore/viewExtensions don't have certificates so all the built-in extensions were not loaded.
For fixing this problem I'm not adding entires to DirectoriesToVerifyCertificates so doesn't check for extensions with certificates in DynamoCore/extensions and DynamoCore/viewExtensions then are loaded correctly.

@RobertGlobant20
Copy link
Contributor Author

But I anticipate that probably we need to think more about getting rid of CommonDataDirectory because also from hosts like Revit we are passing the variable pathResolver.CommonDataRootFolder which is used for setting CommonDataDirectory

Ah yes @RobertGlobant20, I did not see this comment until now but I did mention something similar in your other PR #16528 that we may need to just mark it as obsolete but keep it around for compatibility reasons. Good one!

Edit: Also, I think it's worthwhile merging #16528 into this PR so the regressions can be fixed in one go, there are many moving parts if they are kept separated. Thanks!

based in the next code that recently updated please let me know if you still think is a good idea to obsolete the CommonDataDirectory
image

RobertGlobant20 and others added 2 commits October 10, 2025 11:52
The test CannotDeleteProgramDataPath() was deleted due that is trying to delete the %ProgramData%/Packages folder but not doesn't exist anymore

The test CannotUpdateProgramDataPath() was deleted due that is trying to update the %ProgramData%/Packages folder but not doesn't exist anymore

The static strings were updated to be lowercase due that there is a test checking against that specific string so was failing.
@QilongTang
Copy link
Contributor

based in the next code that recently updated please let me know if you still think is a good idea to obsolete the CommonDataDirectory
image

If the property from PathResolver is always pointing to %ProgramData%, then I think it's still worth obsoleting. However, given this PR is now in a good state, I am leaning towards merging and testing this and keep the other work in follow up PR.

@QilongTang QilongTang merged commit bd3154f into DynamoDS:master Oct 13, 2025
26 of 27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants