From cd35fcaeea87b99a6c1e01f3548e442e24f53e0f Mon Sep 17 00:00:00 2001 From: Roberto T Date: Mon, 15 Dec 2025 16:37:45 -0600 Subject: [PATCH 1/6] DYN-9958 WebView2 Cache Folder Location Modifying the SplashScreen Constructor passing the HostInfo so we can know where to create the WebView2 folder --- .../Views/SplashScreen/SplashScreen.xaml.cs | 37 ++++++++++++++++--- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/src/DynamoCoreWpf/Views/SplashScreen/SplashScreen.xaml.cs b/src/DynamoCoreWpf/Views/SplashScreen/SplashScreen.xaml.cs index 78f6568c7fa..7772181d5f2 100644 --- a/src/DynamoCoreWpf/Views/SplashScreen/SplashScreen.xaml.cs +++ b/src/DynamoCoreWpf/Views/SplashScreen/SplashScreen.xaml.cs @@ -10,6 +10,7 @@ using Dynamo.Configuration; using Dynamo.Controls; using Dynamo.Core; +using Dynamo.Interfaces; using Dynamo.Logging; using Dynamo.Models; using Dynamo.Utilities; @@ -37,6 +38,10 @@ public partial class SplashScreen : Window /// public bool CloseWasExplicit { get; private set; } + internal HostAnalyticsInfo? hostAnalyticsInfo { get; private set; } + + internal string userDataFolder { get; private set; } + // Indicates if the SplashScren close button was hit. // Used to ensure that OnClosing is called only once. private bool IsClosing = false; @@ -144,10 +149,20 @@ public void OnRequestStaticSplashScreen() /// Splash Screen Constructor. /// Indicates if the SignIn Button will be enabled(default) or not. /// - public SplashScreen(bool enableSignInButton = true) + public SplashScreen(bool enableSignInButton = true, HostAnalyticsInfo? hostInfo = null, string userDataFolder = "") { InitializeComponent(); + if(hostInfo != null) + { + hostAnalyticsInfo = hostInfo.Value; + } + if(!string.IsNullOrEmpty(userDataFolder)) + { + this.userDataFolder = userDataFolder; + } + + loadingTimer = new Stopwatch(); loadingTimer.Start(); @@ -327,11 +342,23 @@ private void DynamoModel_RequestUpdateLoadBarStatus(SplashScreenLoadEventArgs ar /// private string GetUserDirectory() { - var version = AssemblyHelper.GetDynamoVersion(); + if (!string.IsNullOrEmpty(userDataFolder) && hostAnalyticsInfo != null) + { + var folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + var version = hostAnalyticsInfo.Value.HostVersion; - var folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); - return Path.Combine(Path.Combine(folder, Configurations.DynamoAsString, "Dynamo Core"), - String.Format("{0}.{1}", version.Major, version.Minor)); + return Path.Combine(userDataFolder, + String.Format("{0}.{1}", version.Major, version.Minor)); + } + else + { + var version = AssemblyHelper.GetDynamoVersion(); + + var folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + return Path.Combine(Path.Combine(folder, Configurations.DynamoAsString, "Dynamo Core"), + String.Format("{0}.{1}", version.Major, version.Minor)); + } + } protected override async void OnContentRendered(EventArgs e) From 567a17c692b656f641995ca3a0556b35287d0239 Mon Sep 17 00:00:00 2001 From: Roberto T Date: Tue, 16 Dec 2025 13:54:29 -0600 Subject: [PATCH 2/6] DYN-9958 WebView2 Cache Folder Location I've added new new clases HostStartup and SplashScreenStartupContext, this will be used for setting host information (in this case Revit), with this info now the the UserDirectory used for WebView2 cache will be change depending if we are using DynamoSandbox or DynamoRevit. Finally I've updated the PublicAPI to reflect the changes --- src/DynamoCoreWpf/DynamoCoreWpf.csproj | 2 + src/DynamoCoreWpf/PublicAPI.Unshipped.txt | 10 +++ src/DynamoCoreWpf/UI/HostStartup.cs | 79 +++++++++++++++++++ .../UI/SplashScreenStartupContext.cs | 38 +++++++++ .../Views/HomePage/HomePage.xaml.cs | 7 +- .../PackageManagerWizard.xaml.cs | 25 +++--- .../Views/SplashScreen/SplashScreen.xaml.cs | 47 ++++------- 7 files changed, 158 insertions(+), 50 deletions(-) create mode 100644 src/DynamoCoreWpf/UI/HostStartup.cs create mode 100644 src/DynamoCoreWpf/UI/SplashScreenStartupContext.cs diff --git a/src/DynamoCoreWpf/DynamoCoreWpf.csproj b/src/DynamoCoreWpf/DynamoCoreWpf.csproj index b6ec89e35bf..1d7eb20da7b 100644 --- a/src/DynamoCoreWpf/DynamoCoreWpf.csproj +++ b/src/DynamoCoreWpf/DynamoCoreWpf.csproj @@ -569,6 +569,8 @@ Resources.resx + + diff --git a/src/DynamoCoreWpf/PublicAPI.Unshipped.txt b/src/DynamoCoreWpf/PublicAPI.Unshipped.txt index 4ad5c5a1b71..3642a899fee 100644 --- a/src/DynamoCoreWpf/PublicAPI.Unshipped.txt +++ b/src/DynamoCoreWpf/PublicAPI.Unshipped.txt @@ -1753,6 +1753,7 @@ Dynamo.UI.Views.SplashScreen.OnRequestDynamicSplashScreen() -> void Dynamo.UI.Views.SplashScreen.OnRequestStaticSplashScreen() -> void Dynamo.UI.Views.SplashScreen.RequestLaunchDynamo -> System.Action Dynamo.UI.Views.SplashScreen.SplashScreen(bool enableSignInButton = true) -> void +Dynamo.UI.Views.SplashScreen.SplashScreen(Dynamo.Wpf.UI.SplashScreenStartupContext context, bool enableSignInButton = true) -> void Dynamo.UI.Views.SplashScreen.totalLoadingTime -> long Dynamo.Utilities.MouseClickManager Dynamo.Utilities.MouseClickManager.Click -> System.Windows.Input.MouseButtonEventHandler @@ -3818,12 +3819,21 @@ Dynamo.Wpf.UI.GuidedTour.UpdateLibraryInteractionsEventHandler Dynamo.Wpf.UI.GuidedTour.UpdatePopupLocationEventHandler Dynamo.Wpf.UI.GuidedTour.Welcome Dynamo.Wpf.UI.GuidedTour.Welcome.Welcome(Dynamo.Wpf.UI.GuidedTour.HostControlInfo host, double width, double height) -> void +Dynamo.Wpf.UI.HostStartup +static Dynamo.Wpf.UI.HostStartup.Current.get -> Dynamo.Wpf.UI.SplashScreenStartupContext +static Dynamo.Wpf.UI.HostStartup.TryInitialize(Dynamo.Wpf.UI.SplashScreenStartupContext context) -> bool +static Dynamo.Wpf.UI.HostStartup.Reset() -> void +static Dynamo.Wpf.UI.HostStartup.GetUserDirectory() -> string Dynamo.Wpf.UI.MouseBehaviour Dynamo.Wpf.UI.MouseBehaviour.MouseBehaviour() -> void Dynamo.Wpf.UI.MouseBehaviour.MouseX.get -> double Dynamo.Wpf.UI.MouseBehaviour.MouseX.set -> void Dynamo.Wpf.UI.MouseBehaviour.MouseY.get -> double Dynamo.Wpf.UI.MouseBehaviour.MouseY.set -> void +Dynamo.Wpf.UI.SplashScreenStartupContext +Dynamo.Wpf.UI.SplashScreenStartupContext.SplashScreenStartupContext(Dynamo.Models.HostAnalyticsInfo? hostInfo, string userDataFolder) -> void +Dynamo.Wpf.UI.SplashScreenStartupContext.HostInfo.get -> Dynamo.Models.HostAnalyticsInfo? +Dynamo.Wpf.UI.SplashScreenStartupContext.UserDataFolder.get -> string Dynamo.Wpf.UI.ToastManager Dynamo.Wpf.UI.ToastManager.CloseRealTimeInfoWindow() -> void Dynamo.Wpf.UI.ToastManager.CreateRealTimeInfoWindow(string content, bool stayOpen = false, string headerText = "", string hyperlinkText = "", System.Uri hyperlinkUri = null, System.Uri fileLinkUri = null) -> void diff --git a/src/DynamoCoreWpf/UI/HostStartup.cs b/src/DynamoCoreWpf/UI/HostStartup.cs new file mode 100644 index 00000000000..f20624922af --- /dev/null +++ b/src/DynamoCoreWpf/UI/HostStartup.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Threading; +using Dynamo.Configuration; +using Dynamo.Utilities; + +namespace Dynamo.Wpf.UI +{ + /// + /// Provides static methods and properties for initializing and managing the host startup context during application + /// launch. + /// + /// is intended for use during the application's splash screen or early + /// startup phase, before other core services are available. It allows initialization of a shared startup context + /// and provides access to user-specific directories based on the current host environment. + public static class HostStartup + { + private static int _initialized; + public static SplashScreenStartupContext? Current { get; private set; } + + /// + /// Initialize the HostStartup with the provided context. + /// + /// + /// + public static bool TryInitialize(SplashScreenStartupContext context) + { + if (context == null) return false; + if (Interlocked.CompareExchange(ref _initialized, 1, 0) != 0) return false; + Current = context; + return true; + } + + /// + /// Resets the static state of the class to its initial, uninitialized condition. + /// + /// Call this method to clear any existing state and reinitialize the class as if it had + /// not been used. This is typically used for testing scenarios or to force reinitialization. This method is + /// not thread-safe; ensure that no other threads are accessing the class while calling . + public static void Reset() + { + Current = null; + Interlocked.Exchange(ref _initialized, 0); + } + + /// + /// Gets the path to the user-specific directory for the current application version. + /// + /// The returned directory path is versioned based on the application's major and minor + /// version numbers. If user-specific host information is available, the path is constructed using the host's + /// user data folder; otherwise, it defaults to a standard location under the user's application data + /// folder. + /// A string containing the full path to the user directory for the current application version. The directory + /// may not exist and may need to be created by the caller. + public static string GetUserDirectory() + { + //we need to use userDataFolder and hostAnalyticsInfo just in SplashScreen due that PathManager/PathResolver are not created yet when SplashScreen is launched from a host + if (Current != null && !string.IsNullOrEmpty(Current.UserDataFolder) && Current.HostInfo != null) + { + var version = Current.HostInfo.Value.HostVersion; + + return Path.Combine(Current.UserDataFolder, + String.Format("{0}.{1}", version.Major, version.Minor)); + } + else + { + var version = AssemblyHelper.GetDynamoVersion(); + + var folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + return Path.Combine(Path.Combine(folder, Configurations.DynamoAsString, "Dynamo Core"), + String.Format("{0}.{1}", version.Major, version.Minor)); + } + + } + } +} diff --git a/src/DynamoCoreWpf/UI/SplashScreenStartupContext.cs b/src/DynamoCoreWpf/UI/SplashScreenStartupContext.cs new file mode 100644 index 00000000000..ec240d8e574 --- /dev/null +++ b/src/DynamoCoreWpf/UI/SplashScreenStartupContext.cs @@ -0,0 +1,38 @@ +using Dynamo.Models; + +namespace Dynamo.Wpf.UI +{ + /// + /// Provides contextual information for initializing a splash screen during application startup, including host + /// analytics data and the user data folder path. + /// + /// This context is typically used to supply startup-related information to components that + /// display or manage a splash screen. It encapsulates optional host analytics details and the location of the + /// user-specific data directory. + public sealed class SplashScreenStartupContext + { + /// + /// Initializes a new instance of the class with the specified host + /// analytics information and user data folder path. + /// + /// Use this constructor to provide context information required during the splash screen + /// startup process, such as analytics data and the location for user-specific files. + /// The analytics information for the host application, or if not available. + /// The path to the user data folder. If , an empty string is used. + public SplashScreenStartupContext(HostAnalyticsInfo ?hostInfo, string userDataFolder) + { + HostInfo = hostInfo != null? hostInfo:null; + UserDataFolder = userDataFolder ?? string.Empty; + } + + /// + /// Gets information about the host environment for analytics purposes. + /// + public HostAnalyticsInfo? HostInfo { get; } + + /// + /// Gets the path to the user data folder. + /// + public string UserDataFolder { get; } + } +} diff --git a/src/DynamoCoreWpf/Views/HomePage/HomePage.xaml.cs b/src/DynamoCoreWpf/Views/HomePage/HomePage.xaml.cs index 3c04457ab1c..c49bee0f4bf 100644 --- a/src/DynamoCoreWpf/Views/HomePage/HomePage.xaml.cs +++ b/src/DynamoCoreWpf/Views/HomePage/HomePage.xaml.cs @@ -15,6 +15,7 @@ using Dynamo.Models; using Dynamo.UI.Controls; using Dynamo.Utilities; +using Dynamo.Wpf.UI; using Dynamo.Wpf.UI.GuidedTour; using Dynamo.Wpf.Utilities; using DynamoUtilities; @@ -137,11 +138,7 @@ private void DynamoViewModel_PropertyChanged(object sender, System.ComponentMode /// private static string GetUserDirectory() { - var version = AssemblyHelper.GetDynamoVersion(); - - var folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); - return Path.Combine(Path.Combine(folder, "Dynamo", "Dynamo Core"), - String.Format("{0}.{1}", version.Major, version.Minor)); + return HostStartup.GetUserDirectory(); } private async void UserControl_Loaded(object sender, System.Windows.RoutedEventArgs e) diff --git a/src/DynamoCoreWpf/Views/PackageManager/Components/PackageManagerWizard/PackageManagerWizard.xaml.cs b/src/DynamoCoreWpf/Views/PackageManager/Components/PackageManagerWizard/PackageManagerWizard.xaml.cs index d1bfe5fd012..70e7664e2b1 100644 --- a/src/DynamoCoreWpf/Views/PackageManager/Components/PackageManagerWizard/PackageManagerWizard.xaml.cs +++ b/src/DynamoCoreWpf/Views/PackageManager/Components/PackageManagerWizard/PackageManagerWizard.xaml.cs @@ -1,29 +1,30 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; +using System.Text.Json; +using System.Text.Json.Serialization; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; +using Autodesk.DesignScript.Runtime; +using Dynamo.Models; +using Dynamo.PackageManager; +using Dynamo.PackageManager.UI; using Dynamo.Utilities; +using Dynamo.Wpf.UI; using Dynamo.Wpf.Utilities; using DynamoUtilities; +using Greg.Requests; using Microsoft.Web.WebView2.Core; using Microsoft.Web.WebView2.Wpf; -using Autodesk.DesignScript.Runtime; -using System.Text.Json; -using System.Text.Json.Serialization; -using Dynamo.PackageManager; -using Dynamo.PackageManager.UI; using Newtonsoft.Json; -using JsonSerializer = System.Text.Json.JsonSerializer; -using Greg.Requests; using Newtonsoft.Json.Linq; -using Dynamo.Models; -using System.Globalization; +using JsonSerializer = System.Text.Json.JsonSerializer; namespace Dynamo.UI.Views { @@ -1007,11 +1008,7 @@ internal bool ProcessUri(string uri) /// private static string GetUserDirectory() { - var version = AssemblyHelper.GetDynamoVersion(); - - var folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); - return Path.Combine(Path.Combine(folder, "Dynamo", "Dynamo Core"), - String.Format("{0}.{1}", version.Major, version.Minor)); + return HostStartup.GetUserDirectory(); } /// diff --git a/src/DynamoCoreWpf/Views/SplashScreen/SplashScreen.xaml.cs b/src/DynamoCoreWpf/Views/SplashScreen/SplashScreen.xaml.cs index 7772181d5f2..b4d59da70e7 100644 --- a/src/DynamoCoreWpf/Views/SplashScreen/SplashScreen.xaml.cs +++ b/src/DynamoCoreWpf/Views/SplashScreen/SplashScreen.xaml.cs @@ -15,6 +15,7 @@ using Dynamo.Models; using Dynamo.Utilities; using Dynamo.ViewModels; +using Dynamo.Wpf.UI; using Dynamo.Wpf.Utilities; using DynamoUtilities; using Greg.AuthProviders; @@ -38,10 +39,6 @@ public partial class SplashScreen : Window /// public bool CloseWasExplicit { get; private set; } - internal HostAnalyticsInfo? hostAnalyticsInfo { get; private set; } - - internal string userDataFolder { get; private set; } - // Indicates if the SplashScren close button was hit. // Used to ensure that OnClosing is called only once. private bool IsClosing = false; @@ -140,6 +137,8 @@ public void OnRequestStaticSplashScreen() StaticSplashScreenReady?.Invoke(); } + internal SplashScreenStartupContext StartupContext { get; } + /// /// Stores the value that indicates if the SignIn Button will be enabled(default) or not /// @@ -149,20 +148,10 @@ public void OnRequestStaticSplashScreen() /// Splash Screen Constructor. /// Indicates if the SignIn Button will be enabled(default) or not. /// - public SplashScreen(bool enableSignInButton = true, HostAnalyticsInfo? hostInfo = null, string userDataFolder = "") + public SplashScreen(bool enableSignInButton = true) { InitializeComponent(); - if(hostInfo != null) - { - hostAnalyticsInfo = hostInfo.Value; - } - if(!string.IsNullOrEmpty(userDataFolder)) - { - this.userDataFolder = userDataFolder; - } - - loadingTimer = new Stopwatch(); loadingTimer.Start(); @@ -182,6 +171,17 @@ public SplashScreen(bool enableSignInButton = true, HostAnalyticsInfo? hostInfo currentCloseMode = CloseMode.ByOther; } + /// + /// Overloaded Splash Screen Constructor to receive SplashScreenStartupContext information + /// + /// + /// + public SplashScreen(SplashScreenStartupContext context, bool enableSignInButton = true) + :this(enableSignInButton) + { + StartupContext = context; + } + protected override void OnClosing(CancelEventArgs e) { // If we have multiple OnClosing events (ex Clicking the close button multiple times) @@ -342,22 +342,7 @@ private void DynamoModel_RequestUpdateLoadBarStatus(SplashScreenLoadEventArgs ar /// private string GetUserDirectory() { - if (!string.IsNullOrEmpty(userDataFolder) && hostAnalyticsInfo != null) - { - var folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); - var version = hostAnalyticsInfo.Value.HostVersion; - - return Path.Combine(userDataFolder, - String.Format("{0}.{1}", version.Major, version.Minor)); - } - else - { - var version = AssemblyHelper.GetDynamoVersion(); - - var folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); - return Path.Combine(Path.Combine(folder, Configurations.DynamoAsString, "Dynamo Core"), - String.Format("{0}.{1}", version.Major, version.Minor)); - } + return HostStartup.GetUserDirectory(); } From 8f0ab3fd032179a66f17d02485b6729070c2a70a Mon Sep 17 00:00:00 2001 From: Roberto T <61755417+RobertGlobant20@users.noreply.github.com> Date: Thu, 18 Dec 2025 11:18:36 -0600 Subject: [PATCH 3/6] Update src/DynamoCoreWpf/UI/SplashScreenStartupContext.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/DynamoCoreWpf/UI/SplashScreenStartupContext.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DynamoCoreWpf/UI/SplashScreenStartupContext.cs b/src/DynamoCoreWpf/UI/SplashScreenStartupContext.cs index ec240d8e574..03a5ae4ceaf 100644 --- a/src/DynamoCoreWpf/UI/SplashScreenStartupContext.cs +++ b/src/DynamoCoreWpf/UI/SplashScreenStartupContext.cs @@ -21,7 +21,7 @@ public sealed class SplashScreenStartupContext /// The path to the user data folder. If , an empty string is used. public SplashScreenStartupContext(HostAnalyticsInfo ?hostInfo, string userDataFolder) { - HostInfo = hostInfo != null? hostInfo:null; + HostInfo = hostInfo; UserDataFolder = userDataFolder ?? string.Empty; } From 2f06b8daeb0ac60c36c8a3ab88655087b958e5b5 Mon Sep 17 00:00:00 2001 From: Roberto T <61755417+RobertGlobant20@users.noreply.github.com> Date: Thu, 18 Dec 2025 11:18:58 -0600 Subject: [PATCH 4/6] Update src/DynamoCoreWpf/Views/SplashScreen/SplashScreen.xaml.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/DynamoCoreWpf/Views/SplashScreen/SplashScreen.xaml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DynamoCoreWpf/Views/SplashScreen/SplashScreen.xaml.cs b/src/DynamoCoreWpf/Views/SplashScreen/SplashScreen.xaml.cs index b4d59da70e7..11570f806a9 100644 --- a/src/DynamoCoreWpf/Views/SplashScreen/SplashScreen.xaml.cs +++ b/src/DynamoCoreWpf/Views/SplashScreen/SplashScreen.xaml.cs @@ -179,7 +179,7 @@ public SplashScreen(bool enableSignInButton = true) public SplashScreen(SplashScreenStartupContext context, bool enableSignInButton = true) :this(enableSignInButton) { - StartupContext = context; + StartupContext = context; } protected override void OnClosing(CancelEventArgs e) From 2a6b092d4d74ce1b0d66b83a05a9299f91c6ded9 Mon Sep 17 00:00:00 2001 From: Roberto T <61755417+RobertGlobant20@users.noreply.github.com> Date: Thu, 18 Dec 2025 11:19:25 -0600 Subject: [PATCH 5/6] Update src/DynamoCoreWpf/UI/HostStartup.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/DynamoCoreWpf/UI/HostStartup.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DynamoCoreWpf/UI/HostStartup.cs b/src/DynamoCoreWpf/UI/HostStartup.cs index f20624922af..8677dc78ac7 100644 --- a/src/DynamoCoreWpf/UI/HostStartup.cs +++ b/src/DynamoCoreWpf/UI/HostStartup.cs @@ -57,7 +57,7 @@ public static void Reset() /// may not exist and may need to be created by the caller. public static string GetUserDirectory() { - //we need to use userDataFolder and hostAnalyticsInfo just in SplashScreen due that PathManager/PathResolver are not created yet when SplashScreen is launched from a host + // we need to use userDataFolder and hostAnalyticsInfo just in SplashScreen because PathManager/PathResolver are not created yet when SplashScreen is launched from a host if (Current != null && !string.IsNullOrEmpty(Current.UserDataFolder) && Current.HostInfo != null) { var version = Current.HostInfo.Value.HostVersion; From 7c8ec1ec737f99238a327e682f9becec87cb92ed Mon Sep 17 00:00:00 2001 From: Roberto T Date: Thu, 18 Dec 2025 11:38:37 -0600 Subject: [PATCH 6/6] DYN-9958 WebView2 Cache Folder Location Code Review string interpolation instead of String.Format for better readability --- src/DynamoCoreWpf/UI/HostStartup.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/DynamoCoreWpf/UI/HostStartup.cs b/src/DynamoCoreWpf/UI/HostStartup.cs index 8677dc78ac7..d32f5841df4 100644 --- a/src/DynamoCoreWpf/UI/HostStartup.cs +++ b/src/DynamoCoreWpf/UI/HostStartup.cs @@ -62,16 +62,14 @@ public static string GetUserDirectory() { var version = Current.HostInfo.Value.HostVersion; - return Path.Combine(Current.UserDataFolder, - String.Format("{0}.{1}", version.Major, version.Minor)); + return Path.Combine(Current.UserDataFolder,$"{version.Major}.{version.Minor}"); } else { var version = AssemblyHelper.GetDynamoVersion(); var folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); - return Path.Combine(Path.Combine(folder, Configurations.DynamoAsString, "Dynamo Core"), - String.Format("{0}.{1}", version.Major, version.Minor)); + return Path.Combine(Path.Combine(folder, Configurations.DynamoAsString, "Dynamo Core"), $"{version.Major}.{version.Minor}"); } }