Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 78 additions & 34 deletions src/DynamoApplications/StartupUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,17 @@ public static CommandLineArguments Parse(string[] args)
// dll paths we'll import before running a graph
var importPaths = new List<string>() ;

// Local ASM binaries path
var asmPath = string.Empty;

// Allow loaded extensions to control the process lifetime
// and issue commands until the extension calls model.Shutdown().
bool keepAlive = false;
bool showHelp = false;

// Allow Dynamo launcher to identify Dynamo variation for log purpose like analytics, e.g. Dynamo Revit
var hostname = string.Empty;

var optionsSet = new OptionSet().Add("o=|O=", "OpenFilePath, Instruct Dynamo to open headless and run a dyn file at this path", o => openfilepath = o)
.Add("c=|C=", "CommandFilePath, Instruct Dynamo to open a commandfile and run the commands it contains at this path," +
"this option is only supported when run from DynamoSandbox", c => commandFilePath = c)
Expand All @@ -115,6 +122,7 @@ public static CommandLineArguments Parse(string[] args)
" - if you wish to import multiple dlls - use this flag multiple times: -i 'assembly1.dll' -i 'assembly2.dll' ", i => importPaths.Add(i))
.Add("gp=|GP=|geometrypath=|GeometryPath=", "relative or absolute path to a directory containing ASM. When supplied, instead of searching the hard disk for ASM, it will be loaded directly from this path.", gp => asmPath = gp)
.Add("k|K|keepalive", "Keepalive mode, leave the Dynamo process running until a loaded extension shuts it down.", k => keepAlive = k != null)
.Add("hn=|HN=|hostname", "Identify Dynamo variation associated with host", hn => hostname = hn)
;
optionsSet.Parse(args);

Expand All @@ -138,7 +146,8 @@ public static CommandLineArguments Parse(string[] args)
GeometryFilePath = geometryFilePath,
ImportedPaths = importPaths,
ASMPath = asmPath,
KeepAlive = keepAlive
KeepAlive = keepAlive,
HostName = hostname,
};
}

Expand All @@ -157,8 +166,14 @@ private static void ShowHelp(OptionSet opSet)
public IEnumerable<String> ImportedPaths { get; set; }
public string ASMPath { get; set; }
public bool KeepAlive { get; set; }
public string HostName { get; set; }
}

/// <summary>
/// Attempts to load the geometry library binaries using the location params.
/// </summary>
/// <param name="geometryFactoryPath">libG ProtoInterface path</param>
/// <param name="preloaderLocation">libG folder path</param>
public static void PreloadShapeManager(ref string geometryFactoryPath, ref string preloaderLocation)
{
var exePath = Assembly.GetExecutingAssembly().Location;
Expand All @@ -178,34 +193,81 @@ public static void PreloadShapeManager(ref string geometryFactoryPath, ref strin
}

/// <summary>
///if we are building a model for CLI mode, then we don't want to start an updateManager
///for now, building an updatemanager instance requires finding Dynamo install location
///which if we are running on mac os or *nix will use different logic then SandboxLookup
/// if we are building a model for CLI mode, then we don't want to start an updateManager
/// for now, building an updatemanager instance requires finding Dynamo install location
/// which if we are running on mac os or *nix will use different logic then SandboxLookup
/// </summary>
private static IUpdateManager InitializeUpdateManager()
/// <param name="hostName">Dynamo variation identified by host.</param>
/// <returns></returns>
private static IUpdateManager InitializeUpdateManager(string hostName = "")
{
var cfg = UpdateManagerConfiguration.GetSettings(new SandboxLookUp());
var um = new Dynamo.Updates.UpdateManager(cfg);
var um = new Dynamo.Updates.UpdateManager(cfg)
{
HostName = hostName
};
Debug.Assert(cfg.DynamoLookUp != null);
return um;
}


/// <summary>
/// Use this overload to construct a DynamoModel when the location of ASM to use is known and host name is known.
/// </summary>
/// <param name="CLImode">CLI mode starts the model in test mode and uses a separate path resolver.</param>
/// <param name="asmPath">Path to directory containing geometry library binaries</param>
/// <param name="hostName">Dynamo variation identified by host.</param>
/// <returns></returns>
public static DynamoModel MakeModel(bool CLImode, string asmPath = "", string hostName ="")
{
PreloadASM(asmPath, out string geometryFactoryPath, out string preloaderLocation);
return StartDynamoWithDefaultConfig(CLImode, geometryFactoryPath, preloaderLocation, hostName);

}

/// <summary>
/// TODO (DYN-2118) remove this method in 3.0 and unify this method with the overload above.
/// Use this overload to construct a DynamoModel when the location of ASM to use is known.
/// </summary>
/// <param name="CLImode">CLI mode starts the model in test mode and uses a seperate path resolver.</param>
/// <param name="asmPath">Path to directory containing geometry library binaries</param>
/// <returns></returns>
[Obsolete("This method will be removed in Dynamo 3.0 - please use the version with more parameters")]
public static DynamoModel MakeModel(bool CLImode, string asmPath)
{
//get sandbox executing location - this is where libG will be located.
var exePath = Assembly.GetExecutingAssembly().Location;
var rootFolder = Path.GetDirectoryName(exePath);
//defaults - these will fail.
var preloaderLocation = "libg_0_0_0";
var geometryFactoryPath = Path.Combine(preloaderLocation, DynamoShapeManager.Utilities.GeometryFactoryAssembly);
PreloadASM(asmPath, out string geometryFactoryPath, out string preloaderLocation);
return StartDynamoWithDefaultConfig(CLImode, geometryFactoryPath, preloaderLocation);
}

//TODO (DYN-2118) remove this method in 3.0 and unify this method with the overload above.
[Obsolete("This method will be removed in Dynamo 3.0 - please use the version with more parameters")]
public static DynamoModel MakeModel(bool CLImode)
{
PreloadASM(string.Empty, out string geometryFactoryPath, out string preloaderLocation);
return StartDynamoWithDefaultConfig(CLImode, geometryFactoryPath, preloaderLocation);
}

private static void PreloadASM(string asmPath, out string geometryFactoryPath, out string preloaderLocation )
{
if (string.IsNullOrEmpty(asmPath))
{
geometryFactoryPath = string.Empty;
preloaderLocation = string.Empty;
try
{
PreloadShapeManager(ref geometryFactoryPath, ref preloaderLocation);
}
catch (Exception e)
{
ASMPreloadFailure?.Invoke(e.Message);
}
return;
}

// get sandbox executing location - this is where libG will be located.
var rootFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
// defaults - preload these will fail.
preloaderLocation = "libg_0_0_0";
geometryFactoryPath = Path.Combine(preloaderLocation, DynamoShapeManager.Utilities.GeometryFactoryAssembly);

try
{
Expand All @@ -222,40 +284,22 @@ public static DynamoModel MakeModel(bool CLImode, string asmPath)
//load asm and libG.
DynamoShapeManager.Utilities.PreloadAsmFromPath(preloaderLocation, asmPath);
}
catch(Exception e)
catch (Exception e)
{
Console.WriteLine("A problem occured while trying to load ASM or LibG");
Console.WriteLine($"{e?.Message} : {e?.StackTrace}");
}
return StartDynamoWithDefaultConfig(CLImode, geometryFactoryPath, preloaderLocation);

}
//TODO (DYN-2118) remove this method in 3.0 and unify this method with the overload above.
public static DynamoModel MakeModel(bool CLImode)
{
var geometryFactoryPath = string.Empty;
var preloaderLocation = string.Empty;
try
{
PreloadShapeManager(ref geometryFactoryPath, ref preloaderLocation);
}
catch(Exception e)
{
ASMPreloadFailure?.Invoke(e.Message);
}

return StartDynamoWithDefaultConfig(CLImode, geometryFactoryPath, preloaderLocation);
}

private static DynamoModel StartDynamoWithDefaultConfig(bool CLImode, string geometryFactoryPath, string preloaderLocation)
private static DynamoModel StartDynamoWithDefaultConfig(bool CLImode, string geometryFactoryPath, string preloaderLocation, string hostName = "")
{
var config = new DynamoModel.DefaultStartConfiguration()
{
GeometryFactoryPath = geometryFactoryPath,
ProcessMode = TaskProcessMode.Asynchronous
};

config.UpdateManager = CLImode ? null : InitializeUpdateManager();
config.UpdateManager = CLImode ? null : InitializeUpdateManager(hostName);
config.StartInTestMode = CLImode ? true : false;
config.PathResolver = CLImode ? new CLIPathResolver(preloaderLocation) as IPathResolver : new SandboxPathResolver(preloaderLocation) as IPathResolver;

Expand Down
6 changes: 5 additions & 1 deletion src/DynamoCLI/CommandLineRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ private static XmlDocument RunCommandLineArgs(DynamoModel model, StartupUtils.Co
Console.WriteLine("geometryFilePath option is only available when running DynamoWPFCLI, not DynamoCLI");
}

if (!(string.IsNullOrEmpty(cmdLineArgs.HostName)))
{
model.HostName = cmdLineArgs.HostName;
}

cmdLineArgs.ImportedPaths.ToList().ForEach(path =>
{
ImportAssembly(model, path);
Expand All @@ -69,7 +74,6 @@ private static XmlDocument RunCommandLineArgs(DynamoModel model, StartupUtils.Co
return null;
}


model.OpenFileFromPath(cmdLineArgs.OpenFilePath, true);
Console.WriteLine("loaded file");
model.EvaluationCompleted += (o, args) => { evalComplete = true; };
Expand Down
30 changes: 13 additions & 17 deletions src/DynamoSandbox/DynamoCoreSetup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ class DynamoCoreSetup
{
private SettingsMigrationWindow migrationWindow;
private DynamoViewModel viewModel = null;
private string commandFilePath;
private readonly string commandFilePath;
private Stopwatch startupTimer = Stopwatch.StartNew();
private string ASMPath;
private readonly string ASMPath;
private readonly string hostName;
private const string sandboxWikiPage = @"https://github.com/DynamoDS/Dynamo/wiki/How-to-Utilize-Dynamo-Builds";

[DllImport("msvcrt.dll")]
Expand All @@ -35,6 +36,7 @@ public DynamoCoreSetup(string[] args)
_putenv(locale);
commandFilePath = cmdLineArgs.CommandFilePath;
ASMPath = cmdLineArgs.ASMPath;
hostName = cmdLineArgs.HostName;
}

public void RunApplication(Application app)
Expand All @@ -44,24 +46,17 @@ public void RunApplication(Application app)
DynamoModel.RequestMigrationStatusDialog += MigrationStatusDialogRequested;
DynamoModel model;
Dynamo.Applications.StartupUtils.ASMPreloadFailure += ASMPreloadFailureHandler;
if (!String.IsNullOrEmpty(ASMPath))
{
model = Dynamo.Applications.StartupUtils.MakeModel(false,ASMPath);
}
else
{
model = Dynamo.Applications.StartupUtils.MakeModel(false);
}

model = Dynamo.Applications.StartupUtils.MakeModel(false, ASMPath ?? string.Empty, hostName);

viewModel = DynamoViewModel.Start(
new DynamoViewModel.StartConfiguration()
{
CommandFilePath = commandFilePath,
DynamoModel = model,
Watch3DViewModel =
Watch3DViewModel =
HelixWatch3DViewModel.TryCreateHelixWatch3DViewModel(
null,
new Watch3DViewModelStartupParams(model),
new Watch3DViewModelStartupParams(model),
model.Logger),
ShowLogin = true
});
Expand Down Expand Up @@ -104,22 +99,23 @@ public void RunApplication(Application app)
{
//show a message dialog box with the exception so the user
//can effectively report the issue.
var shortStackTrace = String.Join(Environment.NewLine,e.StackTrace.Split(Environment.NewLine.ToCharArray()).Take(10));
var shortStackTrace = String.Join(Environment.NewLine, e.StackTrace.Split(Environment.NewLine.ToCharArray()).Take(10));

var result = MessageBox.Show($"{Resources.SandboxCrashMessage} {Environment.NewLine} {e.Message}" +
$" {Environment.NewLine} {e.InnerException?.Message} {Environment.NewLine} {shortStackTrace} {Environment.NewLine} " +
Environment.NewLine + string.Format(Resources.SandboxBuildsPageDialogMessage, sandboxWikiPage),

"DynamoSandbox",
MessageBoxButton.YesNo,MessageBoxImage.Error);
MessageBoxButton.YesNo, MessageBoxImage.Error);

if(result == MessageBoxResult.Yes)
if (result == MessageBoxResult.Yes)
{
System.Diagnostics.Process.Start(sandboxWikiPage);
}
}
}
catch {
catch
{
}

Debug.WriteLine(e.Message);
Expand Down
5 changes: 5 additions & 0 deletions src/DynamoWPFCLI/CommandLineRunnerWPF.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ private static XmlDocument RunCommandLineArgs(DynamoViewModel viewModel, Startup
Console.WriteLine("commandFilePath option is only available when running DynamoSandbox, not DynamoWPFCLI");
}

if (!(string.IsNullOrEmpty(cmdLineArgs.HostName)))
{
viewModel.Model.HostName = cmdLineArgs.HostName;
}

cmdLineArgs.ImportedPaths.ToList().ForEach(path =>
{
ImportAssembly(viewModel.Model, path);
Expand Down
12 changes: 12 additions & 0 deletions test/Libraries/CommandLineTests/CommandLineTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,18 @@ public void CanOpenAndRunDynamoModelWithCommandLineRunner()
AssertPreviewValue("4c5889ac-7b91-4fb5-aaad-a2128b533279", 4.0);
}

[Test]
public void CanSetHostNameWithCommandLineRunner()
{
var openpath = Path.Combine(TestDirectory, @"core\math\Add.dyn");
var hostName = "DynamoFormIt";
var runner = new DynamoCLI.CommandLineRunner(this.CurrentDynamoModel);
string commandstring = $"/o {openpath} /hn {hostName}";

runner.Run(CommandstringToArgs(commandstring));
Assert.AreEqual(this.CurrentDynamoModel.HostName, "DynamoFormIt");
}

[Test]
public void ImportingAnAssemblyDoesNotEffectCustomNodePaths()
{
Expand Down
14 changes: 11 additions & 3 deletions test/System/IntegrationTests/DynamoApplicationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class DynamoApplicationTests
public void DynamoSandboxLoadsASMFromValidPath()
{
var versions = new List<Version>(){

new Version(225, 0, 0),
new Version(226, 0, 0),
new Version(227, 0, 0)
Expand All @@ -34,8 +34,8 @@ public void DynamoSandboxLoadsASMFromValidPath()
// asm modules in the nunit-agent process.
dynamoSandbox = System.Diagnostics.Process.Start(Path.Combine(coreDirectory, "DynamoSandbox.exe"), $"-gp \"{locatedPath}\"");
dynamoSandbox.WaitForInputIdle();
var firstASMmodulePath = string.Empty;

var firstASMmodulePath = string.Empty;
foreach (ProcessModule module in dynamoSandbox.Modules)
{
if (module.FileName.Contains("ASMAHL"))
Expand All @@ -56,6 +56,13 @@ public void DynamoSandboxLoadsASMFromValidPath()
}
}

[Test]
public void DynamoMakeModelWithHostName()
{
var model = Dynamo.Applications.StartupUtils.MakeModel(false, string.Empty, "DynamoFormIt");
Assert.AreEqual(model.HostName, "DynamoFormIt");
}

[Test]
public void IfASMPathInvalidExceptionNotThrown()
{
Expand All @@ -67,6 +74,7 @@ public void IfASMPathInvalidExceptionNotThrown()
});

}

[Test]
public void GetVersionFromASMPath_returnsFileVersionForMockdll()
{
Expand Down