diff --git a/Source/v2/Meadow.Cli/Commands/Current/App/AppBuildCommand.cs b/Source/v2/Meadow.Cli/Commands/Current/App/AppBuildCommand.cs index 5513faa9..2d3227e6 100644 --- a/Source/v2/Meadow.Cli/Commands/Current/App/AppBuildCommand.cs +++ b/Source/v2/Meadow.Cli/Commands/Current/App/AppBuildCommand.cs @@ -1,5 +1,7 @@ using CliFx.Attributes; +using CliFx.Infrastructure; using Meadow.Cli; +using Meadow.Hcom; using Microsoft.Extensions.Logging; namespace Meadow.CLI.Commands.DeviceManagement; @@ -15,13 +17,13 @@ public class AppBuildCommand : BaseCommand [CommandParameter(0, Name = "Path to project file", IsRequired = false)] public string? Path { get; set; } = default!; - public AppBuildCommand(IPackageManager packageManager, ISettingsManager settingsManager, ILoggerFactory loggerFactory) - : base(settingsManager, loggerFactory) + public AppBuildCommand(IPackageManager packageManager, ILoggerFactory loggerFactory) + : base(loggerFactory) { _packageManager = packageManager; } - protected override async ValueTask ExecuteCommand(CancellationToken cancellationToken) + protected override async ValueTask ExecuteCommand(CancellationToken? cancellationToken) { string path = Path == null ? AppDomain.CurrentDomain.BaseDirectory @@ -33,25 +35,25 @@ protected override async ValueTask ExecuteCommand(CancellationToken cancellation // is it a valid directory? if (!Directory.Exists(path)) { - Logger.LogError($"Invalid application path '{path}'"); + Logger?.LogError($"Invalid application path '{path}'"); return; } } if (Configuration == null) Configuration = "Release"; - Logger.LogInformation($"Building {Configuration} configuration of {path}..."); + Logger?.LogInformation($"Building {Configuration} configuration of {path}..."); // TODO: enable cancellation of this call var success = _packageManager.BuildApplication(path, Configuration); if (!success) { - Logger.LogError($"Build failed!"); + Logger?.LogError($"Build failed!"); } else { - Logger.LogError($"Build success."); + Logger?.LogError($"Build success."); } } } \ No newline at end of file diff --git a/Source/v2/Meadow.Cli/Commands/Current/App/AppDeployCommand.cs b/Source/v2/Meadow.Cli/Commands/Current/App/AppDeployCommand.cs index 535c718c..103991af 100644 --- a/Source/v2/Meadow.Cli/Commands/Current/App/AppDeployCommand.cs +++ b/Source/v2/Meadow.Cli/Commands/Current/App/AppDeployCommand.cs @@ -1,4 +1,5 @@ using CliFx.Attributes; +using CliFx.Infrastructure; using Meadow.Cli; using Meadow.Hcom; using Microsoft.Extensions.Logging; @@ -96,4 +97,4 @@ protected override async ValueTask ExecuteCommand(IMeadowConnection connection, await connection.RuntimeEnable(cancellationToken); } } -} +} \ No newline at end of file diff --git a/Source/v2/Meadow.Cli/Commands/Current/App/AppTrimCommand.cs b/Source/v2/Meadow.Cli/Commands/Current/App/AppTrimCommand.cs index 6fe51fec..b56f4047 100644 --- a/Source/v2/Meadow.Cli/Commands/Current/App/AppTrimCommand.cs +++ b/Source/v2/Meadow.Cli/Commands/Current/App/AppTrimCommand.cs @@ -1,4 +1,5 @@ using CliFx.Attributes; +using CliFx.Infrastructure; using Meadow.Cli; using Microsoft.Extensions.Logging; @@ -15,13 +16,13 @@ public class AppTrimCommand : BaseCommand [CommandParameter(0, Name = "Path to project file", IsRequired = false)] public string? Path { get; set; } = default!; - public AppTrimCommand(IPackageManager packageManager, ISettingsManager settingsManager, ILoggerFactory loggerFactory) - : base(settingsManager, loggerFactory) + public AppTrimCommand(IPackageManager packageManager, ILoggerFactory loggerFactory) + : base(loggerFactory) { _packageManager = packageManager; } - protected override async ValueTask ExecuteCommand(CancellationToken cancellationToken) + protected override async ValueTask ExecuteCommand(CancellationToken? cancellationToken) { string path = Path == null ? AppDomain.CurrentDomain.BaseDirectory @@ -35,7 +36,7 @@ protected override async ValueTask ExecuteCommand(CancellationToken cancellation // is it a valid directory? if (!Directory.Exists(path)) { - Logger.LogError($"Invalid application path '{path}'"); + Logger?.LogError($"Invalid application path '{path}'"); return; } @@ -44,7 +45,7 @@ protected override async ValueTask ExecuteCommand(CancellationToken cancellation if (candidates.Length == 0) { - Logger.LogError($"Cannot find a compiled application at '{path}'"); + Logger?.LogError($"Cannot find a compiled application at '{path}'"); return; } @@ -56,8 +57,8 @@ protected override async ValueTask ExecuteCommand(CancellationToken cancellation } // if no configuration was provided, find the most recently built - Logger.LogInformation($"Trimming {file.FullName} (this may take a few seconds)..."); + Logger?.LogInformation($"Trimming {file.FullName} (this may take a few seconds)..."); - await _packageManager.TrimApplication(file, false, null, cancellationToken); + await _packageManager.TrimApplication(file, false, null, cancellationToken ?? default); } } diff --git a/Source/v2/Meadow.Cli/Commands/Current/BaseCommand.cs b/Source/v2/Meadow.Cli/Commands/Current/BaseCommand.cs index dad0c13b..f3833323 100644 --- a/Source/v2/Meadow.Cli/Commands/Current/BaseCommand.cs +++ b/Source/v2/Meadow.Cli/Commands/Current/BaseCommand.cs @@ -1,34 +1,37 @@ using CliFx; using CliFx.Infrastructure; -using Meadow.Cli; +using Meadow.Hcom; using Microsoft.Extensions.Logging; namespace Meadow.CLI.Commands.DeviceManagement; public abstract class BaseCommand : ICommand { - protected ILogger Logger { get; } - protected ISettingsManager SettingsManager { get; } + protected ILogger? Logger { get; } + protected ILoggerFactory? LoggerFactory { get; } + protected IConsole? Console { get; private set; } - public BaseCommand(ISettingsManager settingsManager, ILoggerFactory loggerFactory) + public BaseCommand(ILoggerFactory? loggerFactory) { - Logger = loggerFactory.CreateLogger(); - SettingsManager = settingsManager; + LoggerFactory = loggerFactory; + Logger = loggerFactory?.CreateLogger(); } - protected abstract ValueTask ExecuteCommand(CancellationToken cancellationToken); + protected abstract ValueTask ExecuteCommand(CancellationToken? cancellationToken); public virtual async ValueTask ExecuteAsync(IConsole console) { - var cancellationToken = console.RegisterCancellationHandler(); + Console = console; + var cancellationToken = Console?.RegisterCancellationHandler(); try { - await ExecuteCommand(cancellationToken); + if (cancellationToken!= null) + await ExecuteCommand(cancellationToken); } catch (Exception ex) { - Logger.LogError(ex.Message); + Logger?.LogError(ex.Message); } } -} +} \ No newline at end of file diff --git a/Source/v2/Meadow.Cli/Commands/Current/BaseFileCommand.cs b/Source/v2/Meadow.Cli/Commands/Current/BaseFileCommand.cs index 3679d8f5..3169212f 100644 --- a/Source/v2/Meadow.Cli/Commands/Current/BaseFileCommand.cs +++ b/Source/v2/Meadow.Cli/Commands/Current/BaseFileCommand.cs @@ -4,7 +4,7 @@ namespace Meadow.CLI.Commands.DeviceManagement; -public abstract class BaseFileCommand : BaseCommand +public abstract class BaseFileCommand : BaseSettingsCommand { protected FileManager FileManager { get; } diff --git a/Source/v2/Meadow.Cli/Commands/Current/BaseSettingsCommand.cs b/Source/v2/Meadow.Cli/Commands/Current/BaseSettingsCommand.cs new file mode 100644 index 00000000..6f65341c --- /dev/null +++ b/Source/v2/Meadow.Cli/Commands/Current/BaseSettingsCommand.cs @@ -0,0 +1,16 @@ +using CliFx.Infrastructure; +using Meadow.Cli; +using Microsoft.Extensions.Logging; + +namespace Meadow.CLI.Commands.DeviceManagement; + +public abstract class BaseSettingsCommand : BaseCommand +{ + protected ISettingsManager SettingsManager { get; } + + public BaseSettingsCommand(ISettingsManager settingsManager, ILoggerFactory? loggerFactory) + : base (loggerFactory) + { + SettingsManager = settingsManager; + } +} \ No newline at end of file diff --git a/Source/v2/Meadow.Cli/Commands/Current/ConfigCommand.cs b/Source/v2/Meadow.Cli/Commands/Current/ConfigCommand.cs index 3c07f021..cceaf836 100644 --- a/Source/v2/Meadow.Cli/Commands/Current/ConfigCommand.cs +++ b/Source/v2/Meadow.Cli/Commands/Current/ConfigCommand.cs @@ -8,59 +8,56 @@ namespace Meadow.CLI.Commands.DeviceManagement; [Command("config", Description = "Read or modify the meadow CLI configuration")] -public class ConfigCommand : ICommand +public class ConfigCommand : BaseSettingsCommand { - private readonly ISettingsManager _settingsManager; - private readonly ILogger? _logger; - [CommandOption("list", IsRequired = false)] public bool List { get; set; } [CommandParameter(0, Name = "Settings", IsRequired = false)] - public string[] Settings { get; set; } + public string[]? Settings { get; set; } public ConfigCommand(ISettingsManager settingsManager, ILoggerFactory? loggerFactory) + : base(settingsManager, loggerFactory) { - _logger = loggerFactory?.CreateLogger(); - _settingsManager = settingsManager; + } - public async ValueTask ExecuteAsync(IConsole console) + protected override async ValueTask ExecuteCommand(CancellationToken? cancellationToken) { if (List) { - _logger?.LogInformation($"Current CLI configuration"); + Logger?.LogInformation($"Current CLI configuration"); // display all current config - var settings = _settingsManager.GetPublicSettings(); + var settings = SettingsManager.GetPublicSettings(); if (settings.Count == 0) { - _logger?.LogInformation($" "); + Logger?.LogInformation($" "); } else { - foreach (var kvp in _settingsManager.GetPublicSettings()) + foreach (var kvp in SettingsManager.GetPublicSettings()) { - _logger?.LogInformation($" {kvp.Key} = {kvp.Value}"); + Logger?.LogInformation($" {kvp.Key} = {kvp.Value}"); } } } else { - switch (Settings.Length) + switch (Settings?.Length) { case 0: // not valid throw new CommandException($"No setting provided"); case 1: // erase a setting - _logger?.LogInformation($"Deleting Setting {Settings[0]}"); - _settingsManager.DeleteSetting(Settings[0]); + Logger?.LogInformation($"{Environment.NewLine}Deleting Setting {Settings[0]}"); + SettingsManager.DeleteSetting(Settings[0]); break; case 2: // set a setting - _logger?.LogInformation($"Setting {Settings[0]}={Settings[1]}"); - _settingsManager.SaveSetting(Settings[0], Settings[1]); + Logger?.LogInformation($"{Environment.NewLine}Setting {Settings[0]}={Settings[1]}"); + SettingsManager.SaveSetting(Settings[0], Settings[1]); break; default: // not valid; @@ -68,4 +65,4 @@ public async ValueTask ExecuteAsync(IConsole console) } } } -} +} \ No newline at end of file diff --git a/Source/v2/Meadow.Cli/Commands/Current/Dfu/DfuInstallCommand.cs b/Source/v2/Meadow.Cli/Commands/Current/Dfu/DfuInstallCommand.cs index c71926bb..0d3ac4ff 100644 --- a/Source/v2/Meadow.Cli/Commands/Current/Dfu/DfuInstallCommand.cs +++ b/Source/v2/Meadow.Cli/Commands/Current/Dfu/DfuInstallCommand.cs @@ -1,6 +1,8 @@ using CliFx.Attributes; +using CliFx.Infrastructure; using Meadow.Cli; using Meadow.CLI.Core.Internals.Dfu; +using Meadow.Hcom; using Meadow.Software; using Microsoft.Extensions.Logging; using System.Runtime.InteropServices; @@ -9,7 +11,7 @@ namespace Meadow.CLI.Commands.DeviceManagement; [Command("dfu install", Description = "Deploys a built Meadow application to a target device")] -public class DfuInstallCommand : BaseCommand +public class DfuInstallCommand : BaseSettingsCommand { public const string DefaultVersion = "0.11"; @@ -27,7 +29,7 @@ public DfuInstallCommand(ISettingsManager settingsManager, ILoggerFactory logger { } - protected override async ValueTask ExecuteCommand(CancellationToken cancellationToken) + protected override async ValueTask ExecuteCommand(CancellationToken? cancellationToken) { if (Version == null) { @@ -41,7 +43,7 @@ protected override async ValueTask ExecuteCommand(CancellationToken cancellation // valid break; default: - Logger.LogError("Only versions 0.10 and 0.11 are supported."); + Logger?.LogError("Only versions 0.10 and 0.11 are supported."); return; } @@ -49,20 +51,20 @@ protected override async ValueTask ExecuteCommand(CancellationToken cancellation { if (IsAdministrator()) { - await DfuUtils.InstallDfuUtil(FileManager.WildernessTempFolderPath, Version, cancellationToken); + await DfuUtils.InstallDfuUtil(FileManager.WildernessTempFolderPath, Version, cancellationToken ?? default); } else { - Logger.LogError("To install DFU on Windows, you'll need to re-run the command from as an Administrator"); + Logger?.LogError("To install DFU on Windows, you'll need to re-run the command from as an Administrator"); } } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { - Logger.LogWarning("To install DFU on macOS, run: brew install dfu-util"); + Logger?.LogWarning("To install DFU on macOS, run: brew install dfu-util"); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { - Logger.LogWarning( + Logger?.LogWarning( "To install DFU on Linux, use the package manager to install the dfu-util package"); } } @@ -80,4 +82,4 @@ private static bool IsAdministrator() return false; } } -} +} \ No newline at end of file diff --git a/Source/v2/Meadow.Cli/Commands/Current/Firmware/FirmwareDefaultCommand.cs b/Source/v2/Meadow.Cli/Commands/Current/Firmware/FirmwareDefaultCommand.cs index 37687713..a6b5089e 100644 --- a/Source/v2/Meadow.Cli/Commands/Current/Firmware/FirmwareDefaultCommand.cs +++ b/Source/v2/Meadow.Cli/Commands/Current/Firmware/FirmwareDefaultCommand.cs @@ -1,5 +1,7 @@ using CliFx.Attributes; +using CliFx.Infrastructure; using Meadow.Cli; +using Meadow.Hcom; using Meadow.Software; using Microsoft.Extensions.Logging; @@ -16,7 +18,7 @@ public FirmwareDefaultCommand(FileManager fileManager, ISettingsManager settings [CommandParameter(0, Name = "Version number to use as default", IsRequired = true)] public string Version { get; set; } = default!; - protected override async ValueTask ExecuteCommand(CancellationToken cancellationToken) + protected override async ValueTask ExecuteCommand(CancellationToken? cancellationToken) { await FileManager.Refresh(); @@ -32,4 +34,4 @@ protected override async ValueTask ExecuteCommand(CancellationToken cancellation Logger?.LogInformation($"Done."); } -} +} \ No newline at end of file diff --git a/Source/v2/Meadow.Cli/Commands/Current/Firmware/FirmwareDeleteCommand.cs b/Source/v2/Meadow.Cli/Commands/Current/Firmware/FirmwareDeleteCommand.cs index 511a0cc5..3df18ab3 100644 --- a/Source/v2/Meadow.Cli/Commands/Current/Firmware/FirmwareDeleteCommand.cs +++ b/Source/v2/Meadow.Cli/Commands/Current/Firmware/FirmwareDeleteCommand.cs @@ -1,5 +1,7 @@ using CliFx.Attributes; +using CliFx.Infrastructure; using Meadow.Cli; +using Meadow.Hcom; using Meadow.Software; using Microsoft.Extensions.Logging; @@ -16,7 +18,7 @@ public FirmwareDeleteCommand(FileManager fileManager, ISettingsManager settingsM [CommandParameter(0, Name = "Version number to delete", IsRequired = true)] public string Version { get; set; } = default!; - protected override async ValueTask ExecuteCommand(CancellationToken cancellationToken) + protected override async ValueTask ExecuteCommand(CancellationToken? cancellationToken) { await FileManager.Refresh(); @@ -30,4 +32,4 @@ protected override async ValueTask ExecuteCommand(CancellationToken cancellation Logger?.LogInformation($"Done."); } -} +} \ No newline at end of file diff --git a/Source/v2/Meadow.Cli/Commands/Current/Firmware/FirmwareDownloadCommand.cs b/Source/v2/Meadow.Cli/Commands/Current/Firmware/FirmwareDownloadCommand.cs index 65fb7283..f6032380 100644 --- a/Source/v2/Meadow.Cli/Commands/Current/Firmware/FirmwareDownloadCommand.cs +++ b/Source/v2/Meadow.Cli/Commands/Current/Firmware/FirmwareDownloadCommand.cs @@ -1,5 +1,7 @@ using CliFx.Attributes; +using CliFx.Infrastructure; using Meadow.Cli; +using Meadow.Hcom; using Meadow.Software; using Microsoft.Extensions.Logging; @@ -19,7 +21,7 @@ public FirmwareDownloadCommand(FileManager fileManager, ISettingsManager setting [CommandParameter(0, Name = "Version number to download", IsRequired = false)] public string? Version { get; set; } = default!; - protected override async ValueTask ExecuteCommand(CancellationToken cancellationToken) + protected override async ValueTask ExecuteCommand(CancellationToken? cancellationToken) { await FileManager.Refresh(); @@ -79,6 +81,6 @@ protected override async ValueTask ExecuteCommand(CancellationToken cancellation private void OnDownloadProgress(object? sender, long e) { - Console.Write($"Retrieved {e} bytes... \r"); + Logger?.LogInformation($"Retrieved {e} bytes... \r"); } -} +} \ No newline at end of file diff --git a/Source/v2/Meadow.Cli/Commands/Current/PortListCommand.cs b/Source/v2/Meadow.Cli/Commands/Current/PortListCommand.cs index fe887929..b130b103 100644 --- a/Source/v2/Meadow.Cli/Commands/Current/PortListCommand.cs +++ b/Source/v2/Meadow.Cli/Commands/Current/PortListCommand.cs @@ -1,22 +1,33 @@ -using CliFx.Attributes; +using System; +using CliFx.Attributes; +using CliFx.Infrastructure; +using Meadow.Hardware; using Meadow.Hcom; using Microsoft.Extensions.Logging; namespace Meadow.CLI.Commands.DeviceManagement; [Command("port list", Description = "List available local serial ports")] -public class PortListCommand : BaseDeviceCommand +public class PortListCommand : BaseCommand { - public PortListCommand(MeadowConnectionManager connectionManager, ILoggerFactory loggerFactory) - : base(connectionManager, loggerFactory) + public IList? Portlist; + + public PortListCommand(ILoggerFactory loggerFactory) + : base(loggerFactory) { } - protected override async ValueTask ExecuteCommand(IMeadowConnection connection, Hcom.IMeadowDevice device, CancellationToken cancellationToken) + protected override async ValueTask ExecuteCommand(CancellationToken? cancellationToken) { - foreach (var port in await MeadowConnectionManager.GetSerialPorts()) + Portlist = await MeadowConnectionManager.GetSerialPorts(); + if (Portlist.Count > 0) { - Logger.LogInformation("Found Meadow: {port}", port); + var plural = Portlist.Count > 1 ? "s" : string.Empty; + Logger?.LogInformation($"Found the following device{plural} -"); + for (int i = 0; i < Portlist.Count; i++) + { + Logger?.LogInformation($"{i + 1}: {Portlist[i]}"); + } } } -} +} \ No newline at end of file diff --git a/Source/v2/Meadow.Cli/Commands/Current/PortSelectCommand.cs b/Source/v2/Meadow.Cli/Commands/Current/PortSelectCommand.cs new file mode 100644 index 00000000..1ff545ad --- /dev/null +++ b/Source/v2/Meadow.Cli/Commands/Current/PortSelectCommand.cs @@ -0,0 +1,60 @@ +using CliFx.Attributes; +using Meadow.Cli; +using Microsoft.Extensions.Logging; + +namespace Meadow.CLI.Commands.DeviceManagement; + +[Command("port select", Description = "Select a port from a list of available local serial ports")] +public class PortSelectCommand : BaseCommand +{ + public PortSelectCommand(ILoggerFactory loggerFactory) + : base(loggerFactory) + { + } + + protected override async ValueTask ExecuteCommand(CancellationToken? cancellationToken) + { + if (LoggerFactory != null) + { + if (Console != null) + { + var portListCommand = new PortListCommand(LoggerFactory); + + await portListCommand.ExecuteAsync(Console); + + if (portListCommand.Portlist?.Count > 0) + { + if (portListCommand.Portlist?.Count > 1) + { + Logger?.LogInformation($"{Environment.NewLine}Type the number of the port you would like to use.{Environment.NewLine}or just press Enter to keep your current port."); + + byte deviceSelected; + if (byte.TryParse(await Console.Input.ReadLineAsync(), out deviceSelected)) + { + if (deviceSelected > 0 && deviceSelected <= portListCommand.Portlist?.Count) + { + await CallConfigCommand(portListCommand.Portlist[deviceSelected - 1]); + } + } + } + else + { + // Only 1 device attached, let's auto select it + if (portListCommand.Portlist != null) + await CallConfigCommand(portListCommand.Portlist[0]); + } + } + } + } + } + + private async Task CallConfigCommand(string selectedPort) + { + var setCommand = new ConfigCommand(new SettingsManager(), LoggerFactory) + { + Settings = new string[] { "route", selectedPort } + }; + + await setCommand.ExecuteAsync(Console); + } +} \ No newline at end of file diff --git a/Source/v2/Meadow.Cli/DFU/DfuContext.cs b/Source/v2/Meadow.Cli/DFU/DfuContext.cs index 95163a63..c42c2ff7 100644 --- a/Source/v2/Meadow.Cli/DFU/DfuContext.cs +++ b/Source/v2/Meadow.Cli/DFU/DfuContext.cs @@ -15,7 +15,7 @@ public class DfuContext }; // --------------------------- INSTANCE - public static DfuContext Current; + public static DfuContext? Current; public static void Init() { @@ -25,25 +25,32 @@ public static void Init() public static void Dispose() { - Current._context.Dispose(); + Current?._context?.Dispose(); } // --------------------------- INSTANCE - private Context _context; + private Context? _context; - public List GetDevices() + public List? GetDevices() { - return _context.GetDfuDevices(validVendorIDs); + if (_context != null) + return _context.GetDfuDevices(validVendorIDs); + else + return null; } public bool HasCapability(Capabilities caps) { - return _context.HasCapability(caps); + if (_context != null) + return _context.HasCapability(caps); + else + return false; } public void BeginListeningForHotplugEvents() { - _context.BeginListeningForHotplugEvents(); + if (_context != null) + _context.BeginListeningForHotplugEvents(); } } diff --git a/Source/v2/Meadow.Cli/DFU/DfuUtils.cs b/Source/v2/Meadow.Cli/DFU/DfuUtils.cs index 1a020ab7..1ca52084 100644 --- a/Source/v2/Meadow.Cli/DFU/DfuUtils.cs +++ b/Source/v2/Meadow.Cli/DFU/DfuUtils.cs @@ -75,7 +75,7 @@ public static string GetDeviceSerial(IUsbDevice device) } } - return serialNumber; + return serialNumber ?? string.Empty; } public enum DfuFlashFormat @@ -318,6 +318,7 @@ public static async Task InstallDfuUtil( var downloadUrl = $"https://s3-us-west-2.amazonaws.com/downloads.wildernesslabs.co/public/dfu-util-{dfuUtilVersion}-binaries.zip"; var downloadFileName = downloadUrl.Substring(downloadUrl.LastIndexOf("/", StringComparison.Ordinal) + 1); + var response = await client.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead, cancellationToken); if (response.IsSuccessStatusCode == false) diff --git a/Source/v2/Meadow.Cli/PackageManager.AssemblyManager.cs b/Source/v2/Meadow.Cli/PackageManager.AssemblyManager.cs index a2f66282..2ab03650 100644 --- a/Source/v2/Meadow.Cli/PackageManager.AssemblyManager.cs +++ b/Source/v2/Meadow.Cli/PackageManager.AssemblyManager.cs @@ -25,8 +25,16 @@ private string? MeadowAssembliesPath // for now we only support F7 // TODO: add switch and support for other platforms var store = _fileManager.Firmware["Meadow F7"]; - store.Refresh(); - _meadowAssembliesPath = store.DefaultPackage.GetFullyQualifiedPath(store.DefaultPackage.BclFolder); + if (store != null) + { + store.Refresh(); + if (store.DefaultPackage != null) + { + var defaultPackage = store.DefaultPackage; + if (defaultPackage.BclFolder != null) + _meadowAssembliesPath = defaultPackage.GetFullyQualifiedPath(defaultPackage.BclFolder); + } + } } return _meadowAssembliesPath; diff --git a/Source/v2/Meadow.Cli/Properties/launchSettings.json b/Source/v2/Meadow.Cli/Properties/launchSettings.json index ee03220d..0ca4f62d 100644 --- a/Source/v2/Meadow.Cli/Properties/launchSettings.json +++ b/Source/v2/Meadow.Cli/Properties/launchSettings.json @@ -15,6 +15,10 @@ "commandName": "Project", "commandLineArgs": "port list" }, + "Port Select": { + "commandName": "Project", + "commandLineArgs": "port select" + }, "Listen": { "commandName": "Project", "commandLineArgs": "listen" diff --git a/Source/v2/Meadow.Cli/SettingsManager.cs b/Source/v2/Meadow.Cli/SettingsManager.cs index a3e6fb18..eb9c002a 100644 --- a/Source/v2/Meadow.Cli/SettingsManager.cs +++ b/Source/v2/Meadow.Cli/SettingsManager.cs @@ -107,9 +107,14 @@ private Settings GetSettings() { var fi = new FileInfo(Path); - if (!Directory.Exists(fi.Directory.FullName)) + var directory = fi.Directory; + if (directory != null) { - Directory.CreateDirectory(fi.Directory.FullName); + var directoryFullName = directory?.FullName; + if (!string.IsNullOrWhiteSpace(directoryFullName) && !Directory.Exists(directoryFullName)) + { + Directory.CreateDirectory(directoryFullName); + } } if (File.Exists(Path))