diff --git a/src/Config/CS_SDK.props b/src/Config/CS_SDK.props index 75482b9138c..5ad2265ce79 100644 --- a/src/Config/CS_SDK.props +++ b/src/Config/CS_SDK.props @@ -7,6 +7,8 @@ net8.0 + + libg_231_0_0 16.0 $(DotNet) 512 diff --git a/src/DynamoApplications/StartupUtils.cs b/src/DynamoApplications/StartupUtils.cs index 78e663ffbfc..370fb77928f 100644 --- a/src/DynamoApplications/StartupUtils.cs +++ b/src/DynamoApplications/StartupUtils.cs @@ -157,6 +157,7 @@ public static void PreloadShapeManager(ref string geometryFactoryPath, ref strin var versions = new[] { + new Version(231,0,0), new Version(230,0,0), }; diff --git a/src/DynamoCore/DynamoCore.csproj b/src/DynamoCore/DynamoCore.csproj index d076b3fd06b..4fbf0f0a017 100644 --- a/src/DynamoCore/DynamoCore.csproj +++ b/src/DynamoCore/DynamoCore.csproj @@ -33,6 +33,7 @@ + @@ -112,15 +113,16 @@ - $(PkgDynamoVisualProgramming_LibG_230_0_0)\tools\libg_locale + $(PkgDynamoVisualProgramming_LibG_231_0_0)\tools\libg_locale - - - - - + + + + + + @@ -152,9 +154,10 @@ - + + diff --git a/src/DynamoCoreWpf/DynamoCoreWpf.csproj b/src/DynamoCoreWpf/DynamoCoreWpf.csproj index b9f35da89f6..d72d02f25da 100644 --- a/src/DynamoCoreWpf/DynamoCoreWpf.csproj +++ b/src/DynamoCoreWpf/DynamoCoreWpf.csproj @@ -1,4 +1,4 @@ - + true @@ -186,7 +186,7 @@ - + diff --git a/src/DynamoManipulation/DynamoManipulation.csproj b/src/DynamoManipulation/DynamoManipulation.csproj index 089d799430c..df12326978b 100644 --- a/src/DynamoManipulation/DynamoManipulation.csproj +++ b/src/DynamoManipulation/DynamoManipulation.csproj @@ -40,7 +40,7 @@ - + diff --git a/src/Libraries/Analysis/Analysis.csproj b/src/Libraries/Analysis/Analysis.csproj index 19c11770278..dbe43109aa7 100644 --- a/src/Libraries/Analysis/Analysis.csproj +++ b/src/Libraries/Analysis/Analysis.csproj @@ -18,7 +18,7 @@ - + {7858fa8c-475f-4b8e-b468-1f8200778cf8} DynamoCore diff --git a/src/Libraries/CoreNodes/CoreNodes.csproj b/src/Libraries/CoreNodes/CoreNodes.csproj index 7f9538ad80e..ec1765eedec 100644 --- a/src/Libraries/CoreNodes/CoreNodes.csproj +++ b/src/Libraries/CoreNodes/CoreNodes.csproj @@ -19,7 +19,7 @@ - + diff --git a/src/Libraries/GeometryColor/GeometryColor.csproj b/src/Libraries/GeometryColor/GeometryColor.csproj index 27609c43552..d62e7e958e5 100644 --- a/src/Libraries/GeometryColor/GeometryColor.csproj +++ b/src/Libraries/GeometryColor/GeometryColor.csproj @@ -14,7 +14,7 @@ MSB3539;CS1591;NUnit2005;NUnit2007;CS0618;CS0612;CS0672 - + diff --git a/src/Libraries/GeometryUI/GeometryUI.csproj b/src/Libraries/GeometryUI/GeometryUI.csproj index 4f5022990c0..74aa3a02d9d 100644 --- a/src/Libraries/GeometryUI/GeometryUI.csproj +++ b/src/Libraries/GeometryUI/GeometryUI.csproj @@ -17,7 +17,7 @@ - + diff --git a/src/Libraries/GeometryUIWpf/GeometryUIWpf.csproj b/src/Libraries/GeometryUIWpf/GeometryUIWpf.csproj index fd1afa3f5d4..d2b479be624 100644 --- a/src/Libraries/GeometryUIWpf/GeometryUIWpf.csproj +++ b/src/Libraries/GeometryUIWpf/GeometryUIWpf.csproj @@ -21,7 +21,7 @@ - + diff --git a/src/Libraries/Tesellation/Tessellation.csproj b/src/Libraries/Tesellation/Tessellation.csproj index 75fd79244fb..a0bd81d2436 100644 --- a/src/Libraries/Tesellation/Tessellation.csproj +++ b/src/Libraries/Tesellation/Tessellation.csproj @@ -14,7 +14,7 @@ MSB3539;CS1591;NUnit2005;NUnit2007;CS0618;CS0612;CS0672 - + diff --git a/src/Tools/DynamoInstallDetective/AscSDKWrapper.cs b/src/Tools/DynamoInstallDetective/AscSDKWrapper.cs new file mode 100644 index 00000000000..71c3301c529 --- /dev/null +++ b/src/Tools/DynamoInstallDetective/AscSDKWrapper.cs @@ -0,0 +1,182 @@ +using System; +using System.IO; +using Microsoft.Win32; + +namespace DynamoInstallDetective +{ +#if NET6_0_OR_GREATER + [System.Runtime.Versioning.SupportedOSPlatform("windows")] +#endif + /// + /// Autodesk Shared Components SDK + /// + /// There is one or more installed shared components packages for each major version. + /// Major versions are for example 2026, 2027 and 2028 and corresponds to our global launches. + /// Minor versions are for example 1.0.0, 1.1.0, 2.0.0 etc. + /// + /// These packages are ususally installed in "C:\Program Files\Common Files\Autodesk Shared\Components", + /// for example in C:\Program Files\Common Files\Autodesk Shared\Components\2026\1.0.0 for version 1.0.0 of the package used by 2026 products. + /// + /// There is no guarantee that this localtion is used as it can be overridden at deplyments time. Instead, the registry should be queried + /// for the final location. + /// + /// The registry location "HKEY_LOCAL_MACHINE\SOFTWARE\Autodesk\SharedComponents\" contains one key for each major version, + /// for example the key 2026 is used for the 2026 package. + /// + /// Each key will hold two values: + /// Version: The current version of the package + /// InstallPath: The actual location where the package is installed. + /// + /// There is usually only one minor version installed for each major version but there are situations when multiple minor versions can be installed. + /// One of these cases is when testing beta versions of the shared components. The version used can then be overridden by using an environment variable, + /// ACS_VERSION_ that points to the prefered version to use. So to load the 2.0-beta verion of the 2026 components you would + /// set ACS_VERSION_2026 to 2.0-beta. + /// + /// All shared components are currenly installed into one flat directory for each release. Possible future changes include the ability to only install those + /// components that actually is needed. This wrapper might need to be updated at that point. + /// + internal class AscSdkWrapper + { + public enum ASC_STATUS + { + SUCCESS = 0, + UNABLE_TO_SET_INSTALL_PATH = 4, + BAD_ARGS = 5, + REG_FAILED = 6, + FUNCTION_CALL_FAILED = 7, + INITIALIZE_FAILED = 8, + ODIS_SDK_INITIALIZE_FAILED = 9, + ODIS_SDK_LOCK_FAILED = 10, + ODIS_SDK_UNLOCK_FAILED = 11, + INCORRECT_REG_PATH = 12, + EMPTY_REG_VERSION = 13, + FAILED = 100 + }; + + private const string registryKey = @"SOFTWARE\Autodesk\SharedComponents\"; + + private readonly string majorRelease; + private readonly string version; + private bool fetchFromEnv; + private string installPath; + private string regPath; + + /// + /// Allows the basekey to be ovrridden, used by unit tests + /// + public RegistryKey BaseKey { get; set; } = Registry.LocalMachine; + + private ASC_STATUS ReadASCVersionFromEnv() + { + ASC_STATUS status = ASC_STATUS.FAILED; + + var minorVersion = Environment.GetEnvironmentVariable(version); + + if(minorVersion != null) + { + fetchFromEnv = true; + + status = ReadASCInstallPathFromRegistry(majorRelease); + + installPath = Path.Combine(installPath, minorVersion); + + if(status != ASC_STATUS.SUCCESS) + { + fetchFromEnv = false; + } + } + + return status; + } + + private ASC_STATUS ReadASCInstallPathFromRegistry(string majorRelease) + { + ASC_STATUS status = ASC_STATUS.REG_FAILED; + + var registryPath = Path.Combine(BaseKey.Name, registryKey, majorRelease); + if(string.IsNullOrEmpty(regPath)) + { + regPath = registryPath; + } + + const string valueName = @"InstallPath"; + const string versionName = @"Version"; + + string installPath = Registry.GetValue(registryPath, valueName, null) as String; + if (installPath != null) + { + if (!Directory.Exists(installPath)) + { + return ASC_STATUS.INCORRECT_REG_PATH; + } + + if (fetchFromEnv) + { + this.installPath = installPath; + status = ASC_STATUS.SUCCESS; + } + else + { + string version = Registry.GetValue(registryPath, versionName, null) as String; + if (string.IsNullOrEmpty(version)) + { + return ASC_STATUS.EMPTY_REG_VERSION; + } + + this.installPath = Path.Combine(installPath, version); + + if (!Directory.Exists(this.installPath)) + { + return ASC_STATUS.INCORRECT_REG_PATH; + } + status = ASC_STATUS.SUCCESS; + } + } + return status; + } + /// + /// Initialize ASC wrapper + /// + /// Major ASC release, for example 2026 + public AscSdkWrapper(string release) + { + majorRelease = release; + version = @"ACS_VERSION_" + majorRelease; + } + + /// + /// Get the install path for the major release + /// + /// The install path for the major release if successful + /// ASC_STATUS.SUCCESS if path was retrived successfully + public ASC_STATUS GetInstalledPath(ref string installedPath) + { + if(string.IsNullOrEmpty(majorRelease)) + { + return ASC_STATUS.INITIALIZE_FAILED; + } + + var status = ReadASCVersionFromEnv() == ASC_STATUS.SUCCESS ? ASC_STATUS.SUCCESS : ReadASCInstallPathFromRegistry(majorRelease); + installedPath = installPath; + + return status; + } + + /// + /// Get the major version of all ASC packages installed on the local machine + /// + /// An array of major versions, for example ["2026, "2027", "2028"] + public static string[] GetMajorVersions() + { + string[] majorVersions = []; + var baseKey = Registry.LocalMachine; + var subkey = baseKey.OpenSubKey(@"SOFTWARE\Autodesk\SharedComponents"); + if(subkey != null) + { + majorVersions = subkey.GetSubKeyNames(); + subkey.Close(); + } + return majorVersions; + } + } +} diff --git a/src/Tools/DynamoInstallDetective/ProductLookUp.cs b/src/Tools/DynamoInstallDetective/ProductLookUp.cs index fb502c03f5e..99dd112748b 100644 --- a/src/Tools/DynamoInstallDetective/ProductLookUp.cs +++ b/src/Tools/DynamoInstallDetective/ProductLookUp.cs @@ -348,6 +348,62 @@ public virtual Tuple GetVersionInfoFromFile(string filePath) } } +#if NET6_0_OR_GREATER + [SupportedOSPlatform("windows")] +#endif + /// + /// Helper class for looking up the install directories for all installed ASC components + /// + public class InstalledAscLookUp : InstalledProductLookUp + { + const string asc = @"Autodesk Shared Components"; + + /// + /// Constructor + /// + /// File to look for + public InstalledAscLookUp(string fileLookup) : base(asc, fileLookup) + { + } + + /// + /// Get all major ASC versions + /// + /// + internal override IEnumerable<(string DisplayName, string ProductKey)> GetProductNameAndCodeList() + { + var list = AscSdkWrapper.GetMajorVersions().Select(x => (DisplayName: x, ProductKey: string.Empty)); + return list; + } + + /// + /// The result is never used but still needs to be overridden + /// + /// + public override IEnumerable GetProductNameList() + { + var list = new List(); + return list; + } + + /// + /// Get the install location for the ASC component + /// + /// ASC major verion + /// + public override string GetInstallLocationFromProductName(string name) + { + AscSdkWrapper asc = new AscSdkWrapper(name); + string path = string.Empty; + if(asc.GetInstalledPath(ref path) == AscSdkWrapper.ASC_STATUS.SUCCESS) + { + return path; + } + + return null; + } + } + #if NET6_0_OR_GREATER [SupportedOSPlatform("windows")] #endif diff --git a/src/Tools/DynamoInstallDetective/Utilities.cs b/src/Tools/DynamoInstallDetective/Utilities.cs index a4f5fe3e729..f2f8a36e404 100644 --- a/src/Tools/DynamoInstallDetective/Utilities.cs +++ b/src/Tools/DynamoInstallDetective/Utilities.cs @@ -94,6 +94,10 @@ public static IEnumerable FindMultipleProductInstallations(List productS using (RegUtils.StartCache()) { var installs = new InstalledProducts(); + + // Look for ASM in installed ASC packages + installs.LookUpAndInitProducts(new InstalledAscLookUp(fileSearchPattern)); + // Look up products with ASM installed on user's computer foreach (var productSearchPattern in productSearchPatterns) { diff --git a/src/Tools/DynamoShapeManager/Preloader.cs b/src/Tools/DynamoShapeManager/Preloader.cs index 3646a01851f..1f980834c49 100644 --- a/src/Tools/DynamoShapeManager/Preloader.cs +++ b/src/Tools/DynamoShapeManager/Preloader.cs @@ -58,6 +58,7 @@ public class Preloader public Preloader(string rootFolder) : this(rootFolder, new[] { + new Version(231,0,0), new Version(230,0,0), }) { diff --git a/src/Tools/DynamoShapeManager/Utilities.cs b/src/Tools/DynamoShapeManager/Utilities.cs index 0d458b5d319..dfe07fcc49f 100644 --- a/src/Tools/DynamoShapeManager/Utilities.cs +++ b/src/Tools/DynamoShapeManager/Utilities.cs @@ -454,6 +454,8 @@ internal static bool IsASMInstallationComplete(IEnumerable filePaths, in { case 230: return !ASM230DllNames.Except(fileNames).Any(); + case 231: + return true; default: // We don't know this version so it's safest to assume it's not complete. return false; diff --git a/src/Tools/NodeDocumentationMarkdownGenerator/NodeDocumentationMarkdownGenerator.csproj b/src/Tools/NodeDocumentationMarkdownGenerator/NodeDocumentationMarkdownGenerator.csproj index fb551db0c7e..bada63b972e 100644 --- a/src/Tools/NodeDocumentationMarkdownGenerator/NodeDocumentationMarkdownGenerator.csproj +++ b/src/Tools/NodeDocumentationMarkdownGenerator/NodeDocumentationMarkdownGenerator.csproj @@ -12,6 +12,7 @@ + diff --git a/test/Libraries/AnalysisTests/AnalysisTests.csproj b/test/Libraries/AnalysisTests/AnalysisTests.csproj index bca24f6d0c5..57725777cb3 100644 --- a/test/Libraries/AnalysisTests/AnalysisTests.csproj +++ b/test/Libraries/AnalysisTests/AnalysisTests.csproj @@ -10,7 +10,7 @@ AnalysisTests - + diff --git a/test/Libraries/DynamoPythonTests/DynamoPythonTests.csproj b/test/Libraries/DynamoPythonTests/DynamoPythonTests.csproj index a5ccc1139ae..a8f4f323f24 100644 --- a/test/Libraries/DynamoPythonTests/DynamoPythonTests.csproj +++ b/test/Libraries/DynamoPythonTests/DynamoPythonTests.csproj @@ -18,7 +18,7 @@ - + diff --git a/test/Libraries/DynamoUtilitiesTests/ASCLookUpTests.cs b/test/Libraries/DynamoUtilitiesTests/ASCLookUpTests.cs new file mode 100644 index 00000000000..acb4f7820a3 --- /dev/null +++ b/test/Libraries/DynamoUtilitiesTests/ASCLookUpTests.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using DynamoInstallDetective; +using Microsoft.Win32; +using Moq; + +using NUnit.Framework; + +namespace DynamoUtilitiesTests +{ + public class ASCLookUpTests + { + [Test, Category("ASCLookUp"), Category("UnitTests")] + public void GetASCInstallDirectoryWorking() + { + var working = new AscSdkWrapper("WorkingMajorVersion"); + working.BaseKey = Registry.CurrentUser; + + string installDirectory = string.Empty; + + var ret = working.GetInstalledPath(ref installDirectory); + + Assert.AreEqual(ret, AscSdkWrapper.ASC_STATUS.SUCCESS); + Assert.IsNotEmpty(installDirectory); + } + + [Test, Category("ASCLookUp"), Category("UnitTests")] + public void GetASCInstallDirectoryNonWorking() + { + var working = new AscSdkWrapper("nonWorkingMajorVersion"); + working.BaseKey = Registry.CurrentUser; + + string installDirectory = string.Empty; + + var ret = working.GetInstalledPath(ref installDirectory); + + Assert.AreEqual(ret, AscSdkWrapper.ASC_STATUS.INCORRECT_REG_PATH); + Assert.IsNotEmpty(installDirectory); + } + + [Test, Category("ASCLookUp"), Category("UnitTests")] + public void GetASCInstallDirectoryBadVersion() + { + var working = new AscSdkWrapper("badMajorVersion"); + working.BaseKey = Registry.CurrentUser; + + string installDirectory = string.Empty; + + var ret = working.GetInstalledPath(ref installDirectory); + + Assert.AreEqual(ret, AscSdkWrapper.ASC_STATUS.REG_FAILED); + Assert.IsNotEmpty(installDirectory); + } + + [Test, Category("ASCLookUp"), Category("UnitTests")] + public void GetASCInstallDirectoryEmptyVersion() + { + var working = new AscSdkWrapper(""); + working.BaseKey = Registry.CurrentUser; + + string installDirectory = string.Empty; + + var ret = working.GetInstalledPath(ref installDirectory); + + Assert.AreEqual(ret, AscSdkWrapper.ASC_STATUS.INITIALIZE_FAILED); + Assert.IsEmpty(installDirectory); + } + } +} diff --git a/test/Libraries/DynamoUtilitiesTests/Setup.cs b/test/Libraries/DynamoUtilitiesTests/Setup.cs index 1d56d671c3d..8dcde9300ed 100644 --- a/test/Libraries/DynamoUtilitiesTests/Setup.cs +++ b/test/Libraries/DynamoUtilitiesTests/Setup.cs @@ -1,13 +1,16 @@ using System; using System.IO; using System.Reflection; +using System.Security.Principal; using Dynamo.Utilities; +using Microsoft.Win32; using NUnit.Framework; [SetUpFixture] public class Setup { private AssemblyHelper assemblyHelper; + private DirectoryInfo tempDir; [OneTimeSetUp] public void RunBeforeAllTests() @@ -24,6 +27,19 @@ public void RunBeforeAllTests() assemblyHelper = new AssemblyHelper(moduleRootFolder.FullName, resolutionPaths); AppDomain.CurrentDomain.AssemblyResolve += assemblyHelper.ResolveAssembly; + + // Setup fake ASC installs + tempDir = Directory.CreateTempSubdirectory(); + var majorVersion = tempDir.CreateSubdirectory(@"WorkingMajorVersion"); + majorVersion.CreateSubdirectory(@"1.0.0"); + RegistryKey key = Registry.CurrentUser; + var workingMajorVersion = key.CreateSubKey(@"SOFTWARE\Autodesk\SharedComponents\WorkingMajorVersion"); + workingMajorVersion.SetValue(@"Version", @"1.0.0"); + workingMajorVersion.SetValue(@"InstallPath", majorVersion.FullName); + + var nonWorkingMajorVersion = key.CreateSubKey(@"SOFTWARE\Autodesk\SharedComponents\nonWorkingMajorVersion"); + nonWorkingMajorVersion.SetValue(@"Version", @"1.0.0"); + nonWorkingMajorVersion.SetValue(@"InstallPath", @"BadPath"); } [OneTimeTearDown] @@ -31,5 +47,9 @@ public void RunAfterAllTests() { AppDomain.CurrentDomain.AssemblyResolve -= assemblyHelper.ResolveAssembly; assemblyHelper = null; + tempDir.Delete(true); + RegistryKey key = Registry.CurrentUser; + key.DeleteSubKey(@"SOFTWARE\Autodesk\SharedComponents\WorkingMajorVersion"); + key.DeleteSubKey(@"SOFTWARE\Autodesk\SharedComponents\nonWorkingMajorVersion"); } } diff --git a/test/Libraries/GeometryColorTests/GeometryColorTests.csproj b/test/Libraries/GeometryColorTests/GeometryColorTests.csproj index a15cfe86f63..6d845f07446 100644 --- a/test/Libraries/GeometryColorTests/GeometryColorTests.csproj +++ b/test/Libraries/GeometryColorTests/GeometryColorTests.csproj @@ -10,7 +10,7 @@ DisplayTests - + diff --git a/test/Libraries/TestServices/TestServices.csproj b/test/Libraries/TestServices/TestServices.csproj index 84ccea3d6c4..8064c828ad3 100644 --- a/test/Libraries/TestServices/TestServices.csproj +++ b/test/Libraries/TestServices/TestServices.csproj @@ -10,7 +10,7 @@ TestServices - + diff --git a/test/Libraries/WorkflowTests/WorkflowTests.csproj b/test/Libraries/WorkflowTests/WorkflowTests.csproj index 0db70e3c781..1f75b980bfe 100644 --- a/test/Libraries/WorkflowTests/WorkflowTests.csproj +++ b/test/Libraries/WorkflowTests/WorkflowTests.csproj @@ -14,7 +14,7 @@ - +