int IDebugRemoteCorDebug.CreateProcessEx(Microsoft.VisualStudio.Debugger.Interop.IDebugPort2 pPort, string lpApplicationName, string lpCommandLine, System.IntPtr lpProcessAttributes, System.IntPtr lpThreadAttributes, int bInheritHandles, uint dwCreationFlags, System.IntPtr lpEnvironment, string lpCurrentDirectory, ref CorDebugInterop._STARTUPINFO lpStartupInfo, ref CorDebugInterop._PROCESS_INFORMATION lpProcessInformation, uint debuggingFlags, out object ppProcess) { ppProcess = null; try { // CreateProcessEx() is guaranteed to return a valid process object, or throw an exception CorDebugProcess process = CorDebugProcess.CreateProcessEx(pPort, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, ref lpStartupInfo, ref lpProcessInformation, debuggingFlags); // StartDebugging() will either get a connected device into a debuggable state and start the dispatch thread, or throw. process.StartDebugging(this, true); ppProcess = process; return(COM_HResults.S_OK); } catch (ProcessExitException) { MessageCentre.DebugMessage(Resources.ResourceStrings.InitializeProcessFailedProcessDied); return(COM_HResults.S_FALSE); } catch (Exception ex) { MessageCentre.DebugMessage(Resources.ResourceStrings.InitializeProcessFailed); MessageCentre.InternalErrorMessage(false, ex.Message); return(COM_HResults.S_FALSE); } }
int IDebugRemoteCorDebug.DebugActiveProcessEx(IDebugPort2 pPort, uint id, int win32Attach, out object ppProcess) { ppProcess = null; try { MessageCentre.DebugMessage(Resources.ResourceStrings.Attach); AD_PROCESS_ID pid = new AD_PROCESS_ID(); pid.ProcessIdType = (uint)AD_PROCESS_ID_TYPE.AD_PROCESS_ID_SYSTEM; pid.dwProcessId = id; IDebugProcess2 iDebugProcess; pPort.GetProcess(pid, out iDebugProcess); CorDebugProcess process = (CorDebugProcess)iDebugProcess; // StartDebugging() will either get a connected device into a debuggable state and start the dispatch thread, or throw. process.StartDebugging(this, false); ppProcess = process; return(COM_HResults.S_OK); } catch (ProcessExitException) { MessageCentre.DebugMessage(Resources.ResourceStrings.AttachFailedProcessDied); return(COM_HResults.S_FALSE); } catch (Exception ex) { MessageCentre.DebugMessage(Resources.ResourceStrings.AttachFailed); MessageCentre.InternalErrorMessage(false, ex.Message); return(COM_HResults.S_FALSE); } }
public CorDebugProcess GetDeviceProcess(string deviceName, int eachSecondRetryMaxCount) { if (string.IsNullOrEmpty(deviceName)) { throw new Exception("DebugPort.GetDeviceProcess() called with no argument"); } MessageCentre.StartProgressMessage(String.Format(Resources.ResourceStrings.StartDeviceSearch, deviceName, eachSecondRetryMaxCount)); CorDebugProcess process = InternalGetDeviceProcess(deviceName); if (process != null) { return(process); } if (eachSecondRetryMaxCount < 0) { eachSecondRetryMaxCount = 0; } for (int i = 0; i < eachSecondRetryMaxCount && process == null; i++) { System.Threading.Thread.Sleep(1000); process = InternalGetDeviceProcess(deviceName); } MessageCentre.StopProgressMessage(String.Format((process == null) ? Resources.ResourceStrings.DeviceFound : Resources.ResourceStrings.DeviceNotFound, deviceName)); return(process); }
/// <summary> /// Handler for PingDeviceCommand /// </summary> /// <param name="sender"></param> /// <param name="arguments"></param> /// <remarks>OK to use async void because this is a top-level event-handler /// https://channel9.msdn.com/Series/Three-Essential-Tips-for-Async/Tip-1-Async-void-is-for-top-level-event-handlers-only /// </remarks> private async void PingDeviceCommandHandler(object sender, EventArgs arguments) { // yield to give the UI thread a chance to respond to user input await Task.Yield(); MessageCentre.StartProgressMessage($"Pinging {ViewModelLocator.DeviceExplorer.SelectedDevice.Description}..."); try { // disable the button (sender as MenuCommand).Enabled = false; // make sure this device is showing as selected in Device Explorer tree view await ThreadHelper.JoinableTaskFactory.RunAsync(async() => { ViewModelLocator.DeviceExplorer.ForceNanoDeviceSelection(); }); // check if debugger engine exists if (NanoDeviceCommService.Device.DebugEngine == null) { NanoDeviceCommService.Device.CreateDebugEngine(); } // connect to the device if (await NanoDeviceCommService.Device.DebugEngine.ConnectAsync(5000)) { // ping device var connection = NanoDeviceCommService.Device.Ping(); switch (ViewModelLocator.DeviceExplorer.SelectedDevice.DebugEngine.ConnectionSource) { case Tools.Debugger.WireProtocol.ConnectionSource.Unknown: MessageCentre.OutputMessage($"No reply from {ViewModelLocator.DeviceExplorer.SelectedDevice.Description}"); break; case Tools.Debugger.WireProtocol.ConnectionSource.nanoBooter: case Tools.Debugger.WireProtocol.ConnectionSource.nanoCLR: MessageCentre.OutputMessage($"{ViewModelLocator.DeviceExplorer.SelectedDevice.Description} is active running {ViewModelLocator.DeviceExplorer.SelectedDevice.DebugEngine.ConnectionSource.ToString()}"); break; } } else { MessageCentre.OutputMessage($"{ViewModelLocator.DeviceExplorer.SelectedDevice.Description} is not responding, please reboot the device."); } } catch (Exception ex) { } finally { // enable the button (sender as MenuCommand).Enabled = true; MessageCentre.StopProgressMessage(); } }
protected override byte[] GenerateCode(string inputFileName, string inputFileContent) { ThreadHelper.ThrowIfNotOnUIThread(); MemoryStream outputStream = new MemoryStream(); StreamWriter streamWriter = new StreamWriter(outputStream); string inputFileNameWithoutExtension = Path.GetFileNameWithoutExtension(inputFileName); // get VS extension assembly to reach ProcessResourceFiles type Assembly buildTasks = GetType().Assembly; Type typ = buildTasks.GetType("nanoFramework.Tools.ProcessResourceFiles"); if (typ != null) { object processResourceFiles = typ.GetConstructor(new Type[] { }).Invoke(null); typ.GetProperty("StronglyTypedClassName").SetValue(processResourceFiles, inputFileNameWithoutExtension, null); typ.GetProperty("StronglyTypedNamespace").SetValue(processResourceFiles, GetResourcesNamespace(), null); typ.GetProperty("GenerateNestedEnums").SetValue(processResourceFiles, m_fNestedEnums, null); typ.GetProperty("GenerateInternalClass").SetValue(processResourceFiles, m_fInternal, null); typ.GetProperty("IsMscorlib").SetValue(processResourceFiles, m_fMscorlib, null); string resourceName = (string)typ.GetProperty("StronglyTypedNamespace").GetValue(processResourceFiles, null); if (string.IsNullOrEmpty(resourceName)) { resourceName = inputFileNameWithoutExtension; } else { resourceName = string.Format("{0}.{1}", resourceName, inputFileNameWithoutExtension); } typ.GetMethod("CreateStronglyTypedResources").Invoke(processResourceFiles, new object[] { inputFileName, CodeProvider, streamWriter, resourceName }); } else { // this shouldn't happen MessageCentre.InternalErrorMessage("Exception when generating code-behind file. ProcessResourceFiles type missing. Please reinstall the nanoFramework extension."); } return(base.StreamToBytes(outputStream)); }
private void OutputWelcomeMessage() { System.Threading.Tasks.Task.Run(() => { // schedule this to wait for a few seconds before doing it's thing allow VS to load System.Threading.Tasks.Task.Delay(5000); // loaded MessageCentre.OutputMessage($"** nanoFramework extension v{NanoFrameworkExtensionVersion.ToString()} loaded **"); // intro messages MessageCentre.OutputMessage("GitHub repo: https://github.com/nanoframework/Home"); MessageCentre.OutputMessage("Report issues: https://github.com/nanoframework/Home/issues"); MessageCentre.OutputMessage("Join our Discord community: https://discord.gg/gCyBu8T"); MessageCentre.OutputMessage("Join our Hackster.io platform: https://www.hackster.io/nanoframework"); MessageCentre.OutputMessage("Follow us on Twitter: https://twitter.com/nanoframework"); MessageCentre.OutputMessage("Follow our YouTube channel: https://www.youtube.com/channel/UC62nKcuCEhvUKHd9k9QEezQ"); MessageCentre.OutputMessage("Star our GitHub repos: https://github.com/nanoframework/Home"); MessageCentre.OutputMessage("Add a short review or rate the VS extension: https://marketplace.visualstudio.com/items?itemName=vs-publisher-1470366.nanoFrameworkVS2017Extension"); MessageCentre.OutputMessage(Environment.NewLine); }); }
/// <summary> /// Initialization of the package; this method is called right after the package is sited, so this is the place /// where you can put all the initialization code that rely on services provided by VisualStudio. /// </summary> protected override async System.Threading.Tasks.Task InitializeAsync(CancellationToken cancellationToken, IProgress <ServiceProgressData> progress) { // make sure "our" key exists and it's writeable s_instance.UserRegistryRoot.CreateSubKey(EXTENSION_SUBKEY, true); AddService(typeof(NanoDeviceCommService), CreateNanoDeviceCommServiceAsync); // Need to add the View model Locator to the application resource dictionary programmatically // because at the extension level we don't have 'XAML' access to it // try to find if the view model locator is already in the app resources dictionary if (System.Windows.Application.Current.TryFindResource("Locator") == null) { // instantiate the view model locator... ViewModelLocator = new ViewModelLocator(); // ... and add it there System.Windows.Application.Current.Resources.Add("Locator", ViewModelLocator); } SimpleIoc.Default.GetInstance <DeviceExplorerViewModel>().Package = this; await MessageCentre.InitializeAsync(this, "nanoFramework Extension"); await DeviceExplorerCommand.InitializeAsync(this, ViewModelLocator, await GetServiceAsync(typeof(NanoDeviceCommService)) as INanoDeviceCommService); DeployProvider.Initialize(this, ViewModelLocator); // Enable debugger UI context UIContext.FromUIContextGuid(CorDebug.EngineGuid).IsActive = true; await TaskScheduler.Default; SimpleIoc.Default.GetInstance <DeviceExplorerViewModel>().NanoDeviceCommService = await GetServiceAsync(typeof(NanoDeviceCommService)) as INanoDeviceCommService; OutputWelcomeMessage(); await base.InitializeAsync(cancellationToken, progress); }
private void SaveButton_Click(object sender, System.Windows.RoutedEventArgs e) { // setup device network configuration block to save var networkConfigurationToSave = (DataContext as DeviceExplorerViewModel).DeviceNetworkConfiguration; // IPv4 address options if (IPv4Automatic.IsChecked.GetValueOrDefault()) { // IPv4 from DHCP networkConfigurationToSave.StartupAddressMode = AddressMode.DHCP; // clear remaining options networkConfigurationToSave.IPv4Address = IPAddress.None; networkConfigurationToSave.IPv4NetMask = IPAddress.None; networkConfigurationToSave.IPv4GatewayAddress = IPAddress.None; } else { // IPv4 has static configuration networkConfigurationToSave.StartupAddressMode = AddressMode.Static; // clear remaining options networkConfigurationToSave.IPv4Address = IPv4Address.GetAddress(); networkConfigurationToSave.IPv4NetMask = IPv4NetMask.GetAddress(); networkConfigurationToSave.IPv4GatewayAddress = IPv4GatewayAddress.GetAddress(); } // IPv4 DNS options if (IPv4DnsAutomatic.IsChecked.GetValueOrDefault()) { // IPv4 DNS is automatic and provided by DHCP server networkConfigurationToSave.AutomaticDNS = true; // clear DNS addresses networkConfigurationToSave.IPv4DNSAddress1 = IPAddress.None; networkConfigurationToSave.IPv4DNSAddress2 = IPAddress.None; } else { // IPv4 DNS is static networkConfigurationToSave.AutomaticDNS = false; networkConfigurationToSave.IPv4DNSAddress1 = IPv4Dns1Address.GetAddress(); networkConfigurationToSave.IPv4DNSAddress2 = IPv4Dns2Address.GetAddress(); } // IPv6 options are not being handled for now // FIXME networkConfigurationToSave.IPv6Address = IPAddress.None; networkConfigurationToSave.IPv6NetMask = IPAddress.None; networkConfigurationToSave.IPv6GatewayAddress = IPAddress.None; networkConfigurationToSave.IPv6DNSAddress1 = IPAddress.None; networkConfigurationToSave.IPv6DNSAddress2 = IPAddress.None; // check MAC address try { var newMACAddress = MACAddress.Text; var newMACAddressArray = newMACAddress.Split(':'); var dummyMacAddress = newMACAddressArray.Select(a => byte.Parse(a, System.Globalization.NumberStyles.HexNumber)).ToArray(); } catch (Exception ex) { // error parsing MAC address field throw new Exception("Invalid MAC address format. Check value."); } // Wi-Fi config (DataContext as DeviceExplorerViewModel).DeviceWireless80211Configuration.Password = WiFiPassword.Password; MessageCentre.StartProgressMessage($"Uploading network configuration to {(DataContext as DeviceExplorerViewModel).SelectedDevice.Description}..."); // check if debugger engine exists if ((DataContext as DeviceExplorerViewModel).SelectedDevice.DebugEngine == null) { (DataContext as DeviceExplorerViewModel).SelectedDevice.CreateDebugEngine(); } // save network configuration to target if ((DataContext as DeviceExplorerViewModel).SelectedDevice.DebugEngine.UpdateDeviceConfiguration(networkConfigurationToSave, 0)) { if ((DataContext as DeviceExplorerViewModel).DeviceNetworkConfiguration.InterfaceType == NetworkInterfaceType.Wireless80211) { // save Wi-Fi profile to target if ((DataContext as DeviceExplorerViewModel).SelectedDevice.DebugEngine.UpdateDeviceConfiguration((DataContext as DeviceExplorerViewModel).DeviceWireless80211Configuration, 0)) { MessageCentre.OutputMessage($"{(DataContext as DeviceExplorerViewModel).SelectedDevice.Description} network configuration updated."); MessageCentre.StopProgressMessage(); // close on success Close(); } } else { // close on success Close(); } } else { MessageCentre.OutputMessage($"Error updating {(DataContext as DeviceExplorerViewModel).SelectedDevice.Description} network configuration."); MessageCentre.StopProgressMessage(); } }
public async Task DeployAsync(CancellationToken cancellationToken, TextWriter outputPaneWriter) { // just in case.... if ((_viewModelLocator?.DeviceExplorer.SelectedDevice == null)) { // can't debug // throw exception to signal deployment failure throw new Exception("There is no device selected. Please select a device in Device Explorer tool window."); } // get the device here so we are not always carrying the full path to the device NanoDeviceBase device = NanoDeviceCommService.Device; // user feedback await outputPaneWriter.WriteLineAsync($"Getting things ready to deploy assemblies to nanoFramework device: {device.Description}."); List <byte[]> assemblies = new List <byte[]>(); // device needs to be in 'initialized state' for a successful and correct deployment // meaning that is not running nor stopped int retryCount = 0; bool deviceIsInInitializeState = false; try { // check if debugger engine exists if (NanoDeviceCommService.Device.DebugEngine == null) { NanoDeviceCommService.Device.CreateDebugEngine(); } // connect to the device if (await device.DebugEngine.ConnectAsync(5000, true)) { // initial check if (device.DebugEngine.IsDeviceInInitializeState()) { // set flag deviceIsInInitializeState = true; // device is still in initialization state, try resume execution device.DebugEngine.ResumeExecution(); } // handle the workflow required to try resuming the execution on the device // only required if device is not already there // retry 5 times with a 500ms interval between retries while (retryCount++ < _numberOfRetries && deviceIsInInitializeState) { if (!device.DebugEngine.IsDeviceInInitializeState()) { // done here deviceIsInInitializeState = false; break; } // provide feedback to user on the 1st pass if (retryCount == 0) { await outputPaneWriter.WriteLineAsync(ResourceStrings.WaitingDeviceInitialization); } if (device.DebugEngine.ConnectionSource == Tools.Debugger.WireProtocol.ConnectionSource.nanoBooter) { // request nanoBooter to load CLR device.DebugEngine.ExecuteMemory(0); } else if (device.DebugEngine.ConnectionSource == Tools.Debugger.WireProtocol.ConnectionSource.nanoCLR) { // already running nanoCLR try rebooting the CLR device.DebugEngine.RebootDevice(RebootOptions.ClrOnly); } // wait before next pass await Task.Delay(TimeSpan.FromMilliseconds(_timeoutMiliseconds)); } ; Thread.Yield(); // check if device is still in initialized state if (!deviceIsInInitializeState) { // device has left initialization state await outputPaneWriter.WriteLineAsync(ResourceStrings.DeviceInitialized); ////////////////////////////////////////////////////////// // sanity check for devices without native assemblies ?!?! if (device.DeviceInfo.NativeAssemblies.Count == 0) { // there are no assemblies deployed?! throw new DeploymentException($"Couldn't find any native assemblies deployed in {_viewModelLocator.DeviceExplorer.SelectedDevice.Description}! If the situation persists reboot the device."); } // For a known project output assembly path, this shall contain the corresponding // ConfiguredProject: Dictionary <string, ConfiguredProject> configuredProjectsByOutputAssemblyPath = new Dictionary <string, ConfiguredProject>(); // For a known ConfiguredProject, this shall contain the corresponding project output assembly // path: Dictionary <ConfiguredProject, string> outputAssemblyPathsByConfiguredProject = new Dictionary <ConfiguredProject, string>(); // Fill these two dictionaries for all projects contained in the solution // (whether they belong to the deployment or not): await ReferenceCrawler.CollectProjectsAndOutputAssemblyPathsAsync( ProjectService, configuredProjectsByOutputAssemblyPath, outputAssemblyPathsByConfiguredProject); // This HashSet shall contain a list of full paths to all assemblies to be deployed, including // the compiled output assemblies of our solution's project and also all assemblies such as // NuGet packages referenced by those projects. // The HashSet will take care of only containing any string once even if added multiple times. // However, this is dependent on getting all paths always in the same casing. // Be aware that on file systems which ignore casing, we would end up having assemblies added // more than once here if the GetFullPathAsync() methods used below should not always reliably // return the path to the same assembly in the same casing. HashSet <string> assemblyPathsToDeploy = new HashSet <string>(); // Starting with the startup project, collect all assemblies to be deployed. // This will only add assemblies of projects which are actually referenced directly or // indirectly by the startup project. Any project in the solution which is not referenced // directly or indirectly by the startup project will not be included in the list of assemblies // to be deployed. await ReferenceCrawler.CollectAssembliesToDeployAsync( configuredProjectsByOutputAssemblyPath, outputAssemblyPathsByConfiguredProject, assemblyPathsToDeploy, Properties.ConfiguredProject); // build a list with the full path for each DLL, referenced DLL and EXE List <(string path, string version)> assemblyList = new List <(string path, string version)>(); foreach (string assemblyPath in assemblyPathsToDeploy) { // load assembly to get the version var assembly = Assembly.Load(File.ReadAllBytes(assemblyPath)).GetName(); assemblyList.Add((assemblyPath, $"{assembly.Version.ToString(4)}")); } // if there are referenced project, the assembly list contains repeated assemblies so need to use Linq Distinct() // build a list with the PE files corresponding to each DLL and EXE List <(string path, string version)> peCollection = assemblyList.Distinct().Select(a => (a.path.Replace(".dll", ".pe").Replace(".exe", ".pe"), a.version)).ToList(); var checkAssembliesResult = await CheckNativeAssembliesAvailabilityAsync(device.DeviceInfo.NativeAssemblies, peCollection); if (checkAssembliesResult != "") { // can't deploy throw new DeploymentException(checkAssembliesResult); } // Keep track of total assembly size long totalSizeOfAssemblies = 0; // now we will re-deploy all system assemblies foreach ((string path, string version)peItem in peCollection) { // append to the deploy blob the assembly using (FileStream fs = File.Open(peItem.path, FileMode.Open, FileAccess.Read)) { long length = (fs.Length + 3) / 4 * 4; await outputPaneWriter.WriteLineAsync($"Adding {Path.GetFileNameWithoutExtension(peItem.path)} v{peItem.version} ({length.ToString()} bytes) to deployment bundle"); byte[] buffer = new byte[length]; await fs.ReadAsync(buffer, 0, (int)fs.Length); assemblies.Add(buffer); // Increment totalizer totalSizeOfAssemblies += length; } } await outputPaneWriter.WriteLineAsync($"Deploying {peCollection.Count:N0} assemblies to device... Total size in bytes is {totalSizeOfAssemblies.ToString()}."); Thread.Yield(); if (!device.DebugEngine.DeploymentExecute(assemblies, false)) { // throw exception to signal deployment failure throw new DeploymentException("Deploy failed."); } Thread.Yield(); // deployment successful await outputPaneWriter.WriteLineAsync("Deployment successful."); // reset the hash for the connected device so the deployment information can be refreshed _viewModelLocator.DeviceExplorer.LastDeviceConnectedHash = 0; } else { // after retry policy applied seems that we couldn't resume execution on the device... // throw exception to signal deployment failure throw new DeploymentException(ResourceStrings.DeviceInitializationTimeout); } } else { // throw exception to signal deployment failure throw new DeploymentException($"{_viewModelLocator.DeviceExplorer.SelectedDevice.Description} is not responding. Please retry the deployment. If the situation persists reboot the device."); } } catch (DeploymentException ex) { throw ex; } catch (Exception ex) { MessageCentre.InternalErrorMessage($"Unhandled exception with deployment provider: {ex.Message}."); throw new Exception("Unexpected error. Please retry the deployment. If the situation persists reboot the device."); } }
/// <summary> /// Handler for RebootCommand /// </summary> /// <param name="sender"></param> /// <param name="arguments"></param> /// <remarks>OK to use async void because this is a top-level event-handler /// https://channel9.msdn.com/Series/Three-Essential-Tips-for-Async/Tip-1-Async-void-is-for-top-level-event-handlers-only /// </remarks> private async void RebootCommandHandler(object sender, EventArgs arguments) { // yield to give the UI thread a chance to respond to user input await Task.Yield(); try { // disable the button (sender as MenuCommand).Enabled = false; // make sure this device is showing as selected in Device Explorer tree view await ThreadHelper.JoinableTaskFactory.RunAsync(async() => { ViewModelLocator.DeviceExplorer.ForceNanoDeviceSelection(); }); // check if debugger engine exists if (NanoDeviceCommService.Device.DebugEngine == null) { NanoDeviceCommService.Device.CreateDebugEngine(); } // connect to the device if (await NanoDeviceCommService.Device.DebugEngine.ConnectAsync(5000)) { try { NanoDeviceCommService.Device.DebugEngine.RebootDevice(Debugger.RebootOptions.NormalReboot); MessageCentre.OutputMessage($"Sent reboot command to {ViewModelLocator.DeviceExplorer.SelectedDevice.Description}."); // reset the hash for the connected device so the deployment information can be refreshed, if and when requested ViewModelLocator.DeviceExplorer.LastDeviceConnectedHash = 0; // yield to give the UI thread a chance to respond to user input await Task.Yield(); } catch { // report issue to user MessageCentre.OutputMessage($"Error sending reboot command to {ViewModelLocator.DeviceExplorer.SelectedDevice.Description}."); return; } } else { // reset property to force that device capabilities are retrieved on next connection ViewModelLocator.DeviceExplorer.LastDeviceConnectedHash = 0; MessageCentre.OutputMessage($"{ViewModelLocator.DeviceExplorer.SelectedDevice.Description} is not responding, please reboot the device."); return; } } catch (Exception ex) { } finally { // enable the button (sender as MenuCommand).Enabled = true; } }
/// <summary> /// Handler for NetworkConfigCommand /// </summary> /// <param name="sender"></param> /// <param name="arguments"></param> /// <remarks>OK to use async void because this is a top-level event-handler /// https://channel9.msdn.com/Series/Three-Essential-Tips-for-Async/Tip-1-Async-void-is-for-top-level-event-handlers-only /// </remarks> private async void NetworkConfigCommandHandler(object sender, EventArgs arguments) { // yield to give the UI thread a chance to respond to user input await Task.Yield(); try { // disable the button (sender as MenuCommand).Enabled = false; // make sure this device is showing as selected in Device Explorer tree view await ThreadHelper.JoinableTaskFactory.RunAsync(async() => { ViewModelLocator.DeviceExplorer.ForceNanoDeviceSelection(); }); // check if debugger engine exists if (NanoDeviceCommService.Device.DebugEngine == null) { NanoDeviceCommService.Device.CreateDebugEngine(); } // connect to the device if (await NanoDeviceCommService.Device.DebugEngine.ConnectAsync(5000)) { try { // for now, just get the 1st network configuration, if exists var networkConfigurations = NanoDeviceCommService.Device.DebugEngine.GetAllNetworkConfigurations(); if (networkConfigurations.Count > 0) { ViewModelLocator.DeviceExplorer.DeviceNetworkConfiguration = networkConfigurations[0]; } else { ViewModelLocator.DeviceExplorer.DeviceNetworkConfiguration = new Debugger.DeviceConfiguration.NetworkConfigurationProperties(); } // for now, just get the 1st Wi-Fi configuration, if exists var wirellesConfigurations = NanoDeviceCommService.Device.DebugEngine.GetAllWireless80211Configurations(); if (wirellesConfigurations.Count > 0) { ViewModelLocator.DeviceExplorer.DeviceWireless80211Configuration = wirellesConfigurations[0]; } else { ViewModelLocator.DeviceExplorer.DeviceWireless80211Configuration = new Debugger.DeviceConfiguration.Wireless80211ConfigurationProperties(); } // yield to give the UI thread a chance to respond to user input await Task.Yield(); // show network configuration dialogue var networkConfigDialog = new NetworkConfigurationDialog(); networkConfigDialog.HasMinimizeButton = false; networkConfigDialog.HasMaximizeButton = false; networkConfigDialog.ShowModal(); } catch { // report issue to user MessageCentre.OutputMessage($"Error reading {ViewModelLocator.DeviceExplorer.SelectedDevice.Description} configurations."); return; } } else { MessageCentre.OutputMessage($"{ViewModelLocator.DeviceExplorer.SelectedDevice.Description} is not responding, please reboot the device."); return; } } catch (Exception ex) { } finally { // enable the button (sender as MenuCommand).Enabled = true; // clear status bar MessageCentre.StopProgressMessage(); } }
/// <summary> /// Handler for DeviceCapabilitiesCommand /// </summary> /// <param name="sender"></param> /// <param name="arguments"></param> /// <remarks>OK to use async void because this is a top-level event-handler /// https://channel9.msdn.com/Series/Three-Essential-Tips-for-Async/Tip-1-Async-void-is-for-top-level-event-handlers-only /// </remarks> private async void DeviceCapabilitiesCommandHandler(object sender, EventArgs arguments) { // yield to give the UI thread a chance to respond to user input await Task.Yield(); MessageCentre.StartProgressMessage($"Querying {ViewModelLocator.DeviceExplorer.SelectedDevice.Description} capabilities..."); try { // disable the button (sender as MenuCommand).Enabled = false; // make sure this device is showing as selected in Device Explorer tree view await ThreadHelper.JoinableTaskFactory.RunAsync(async() => { ViewModelLocator.DeviceExplorer.ForceNanoDeviceSelection(); }); // only query device if it's different if (ViewModelLocator.DeviceExplorer.SelectedDevice.Description.GetHashCode() != ViewModelLocator.DeviceExplorer.LastDeviceConnectedHash) { // keep device description hash code to avoid get info twice ViewModelLocator.DeviceExplorer.LastDeviceConnectedHash = ViewModelLocator.DeviceExplorer.SelectedDevice.Description.GetHashCode(); // check if debugger engine exists if (NanoDeviceCommService.Device.DebugEngine == null) { NanoDeviceCommService.Device.CreateDebugEngine(); } // connect to the device if (await NanoDeviceCommService.Device.DebugEngine.ConnectAsync(5000)) { try { // get device info var deviceInfo = NanoDeviceCommService.Device.GetDeviceInfo(true); var memoryMap = NanoDeviceCommService.Device.DebugEngine.GetMemoryMap(); var flashMap = NanoDeviceCommService.Device.DebugEngine.GetFlashSectorMap(); var deploymentMap = NanoDeviceCommService.Device.DebugEngine.GetDeploymentMap(); // we have to have a valid device info if (deviceInfo.Valid) { // load view model properties for maps ViewModelLocator.DeviceExplorer.DeviceMemoryMap = new StringBuilder(memoryMap?.ToStringForOutput() ?? "Empty"); ViewModelLocator.DeviceExplorer.DeviceFlashSectorMap = new StringBuilder(flashMap?.ToStringForOutput() ?? "Empty"); ViewModelLocator.DeviceExplorer.DeviceDeploymentMap = new StringBuilder(deploymentMap?.ToStringForOutput() ?? "Empty"); // load view model property for system ViewModelLocator.DeviceExplorer.DeviceSystemInfo = new StringBuilder(deviceInfo?.ToString() ?? "Empty"); } else { // reset property to force that device capabilities are retrieved on next connection ViewModelLocator.DeviceExplorer.LastDeviceConnectedHash = 0; // report issue to user MessageCentre.OutputMessage($"Error retrieving device information from { ViewModelLocator.DeviceExplorer.SelectedDevice.Description}. Please reconnect device."); return; } } catch { // reset property to force that device capabilities are retrieved on next connection ViewModelLocator.DeviceExplorer.LastDeviceConnectedHash = 0; // report issue to user MessageCentre.OutputMessage($"Error retrieving device information from { ViewModelLocator.DeviceExplorer.SelectedDevice.Description}. Please reconnect device."); return; } } else { // reset property to force that device capabilities are retrieved on next connection ViewModelLocator.DeviceExplorer.LastDeviceConnectedHash = 0; MessageCentre.OutputMessage($"{ViewModelLocator.DeviceExplorer.SelectedDevice.Description} is not responding, please reboot the device."); return; } } MessageCentre.OutputMessage(string.Empty); MessageCentre.OutputMessage(string.Empty); MessageCentre.OutputMessage("System Information"); MessageCentre.OutputMessage(ViewModelLocator.DeviceExplorer.DeviceSystemInfo.ToString()); MessageCentre.OutputMessage(string.Empty); MessageCentre.OutputMessage(string.Empty); MessageCentre.OutputMessage("--------------------------------"); MessageCentre.OutputMessage(":: Memory Map ::"); MessageCentre.OutputMessage("--------------------------------"); MessageCentre.OutputMessage(ViewModelLocator.DeviceExplorer.DeviceMemoryMap.ToString()); MessageCentre.OutputMessage(string.Empty); MessageCentre.OutputMessage(string.Empty); MessageCentre.OutputMessage("-----------------------------------------------------------"); MessageCentre.OutputMessage(":: Flash Sector Map ::"); MessageCentre.OutputMessage("-----------------------------------------------------------"); MessageCentre.OutputMessage(ViewModelLocator.DeviceExplorer.DeviceFlashSectorMap.ToString()); MessageCentre.OutputMessage(string.Empty); MessageCentre.OutputMessage(string.Empty); MessageCentre.OutputMessage("Deployment Map"); MessageCentre.OutputMessage(ViewModelLocator.DeviceExplorer.DeviceDeploymentMap.ToString()); MessageCentre.OutputMessage(string.Empty); } catch (Exception ex) { } finally { // enable the button (sender as MenuCommand).Enabled = true; // clear status bar MessageCentre.StopProgressMessage(); } }