using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.IO.Ports; using System.Diagnostics; using MatterHackers.Agg; using MatterHackers.Agg.UI; using MatterHackers.Agg.OpenGlGui; using MatterHackers.PolygonMesh; using MatterHackers.RenderOpenGl; using MatterHackers.VectorMath; using MatterHackers.MatterControl.DataStorage; namespace MatterHackers.MatterControl.PrinterControls.PrinterConnections { public class SetupConnectionWidget : ConnectionWidgetBase { List SerialPortButtonsList = new List(); List BaudRateButtonsList = new List(); FlowLayoutWidget ConnectionControlContainer; FlowLayoutWidget printerModelContainer; FlowLayoutWidget printerMakeContainer; FlowLayoutWidget printerNameContainer; FlowLayoutWidget printerSerialPortContainer; FlowLayoutWidget printerBaudRateContainer; FlowLayoutWidget printerDriverContainer; TextWidget printerModelError; TextWidget printerMakeError; TextWidget printerComPortError; TextWidget printerBaudRateError; TextWidget printerNameError; TextWidget printerDriverMessage; Button printerDriverInstallButton; Printer ActivePrinter; MHTextEditWidget printerNameInput; MHTextEditWidget otherBaudRateInput; LinkButtonFactory linkButtonFactory = new LinkButtonFactory(); Button saveButton; Button cancelButton; GuiWidget comPortLabelWidget; GuiWidget baudRateWidget; RadioButton otherBaudRateRadioButton; bool editBaudRate = true; bool installDriver = true; bool printerComExists = false; TextImageButtonFactory textImageButtonFactory = new TextImageButtonFactory(); TextImageButtonFactory installButtonFactory = new TextImageButtonFactory(); bool addNewPrinterFlag = false; public SetupConnectionWidget(ConnectionWindow windowController, GuiWidget containerWindowToClose, Printer activePrinter = null) : base(windowController, containerWindowToClose) { SetDisplayAttributes(); GuiWidget mainContainer = new FlowLayoutWidget(FlowDirection.TopToBottom); mainContainer.AnchorAll(); mainContainer.Padding = new BorderDouble(3, 0, 3, 5); mainContainer.BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor; string headerTitle; if (activePrinter == null) { headerTitle = string.Format("3-D Printer Setup"); this.addNewPrinterFlag = true; this.ActivePrinter = new Printer(); this.ActivePrinter.Make = null; this.ActivePrinter.Model = null; this.ActivePrinter.Name = "Default Printer"; this.ActivePrinter.BaudRate = "250000"; try { this.ActivePrinter.ComPort = SerialPort.GetPortNames()[0]; } catch { //No active COM ports } } else { this.ActivePrinter = activePrinter; headerTitle = string.Format("Edit - {0}", this.ActivePrinter.Name); } //Create the header row for the widget FlowLayoutWidget headerRow = new FlowLayoutWidget(FlowDirection.LeftToRight); headerRow.Margin = new BorderDouble(0, 3, 0, 0); headerRow.Padding = new BorderDouble(0, 3, 0, 3); headerRow.HAnchor = HAnchor.ParentLeftRight; { TextWidget headerLabel = new TextWidget(headerTitle, pointSize: 14); headerLabel.TextColor = this.defaultTextColor; headerRow.AddChild(headerLabel); } //Create the main control container ConnectionControlContainer = new FlowLayoutWidget(FlowDirection.TopToBottom); ConnectionControlContainer.Padding = new BorderDouble(5); ConnectionControlContainer.BackgroundColor = ActiveTheme.Instance.SecondaryBackgroundColor; ConnectionControlContainer.HAnchor = HAnchor.ParentLeftRight; { ConnectionControlContainer.VAnchor = VAnchor.ParentBottomTop; printerMakeContainer = createPrinterMakeContainer(); printerModelContainer = createPrinterModelContainer(); printerSerialPortContainer = createPrinterSerialPortContainer(); printerBaudRateContainer = createPrinterBaudRateContainer(); printerDriverContainer = createPrinterDriverContainer(); printerNameContainer = createPrinterNameContainer(); ConnectionControlContainer.AddChild(printerMakeContainer); ConnectionControlContainer.AddChild(printerModelContainer); ConnectionControlContainer.AddChild(printerSerialPortContainer); ConnectionControlContainer.AddChild(printerBaudRateContainer); ConnectionControlContainer.AddChild(printerDriverContainer); //ConnectionControlContainer.AddChild(printerNameContainer); } FlowLayoutWidget buttonContainer = new FlowLayoutWidget(FlowDirection.LeftToRight); buttonContainer.HAnchor = HAnchor.ParentLeft | HAnchor.ParentRight; //buttonContainer.VAnchor = VAnchor.BottomTop; buttonContainer.Margin = new BorderDouble(0, 3); { //Construct buttons saveButton = textImageButtonFactory.Generate("Save"); //saveButton.VAnchor = VAnchor.Bottom; cancelButton = textImageButtonFactory.Generate("Cancel"); //cancelButton.VAnchor = VAnchor.Bottom; cancelButton.Click += new ButtonBase.ButtonEventHandler(CancelButton_Click); //Add buttons to buttonContainer buttonContainer.AddChild(saveButton); buttonContainer.AddChild(cancelButton); } mainContainer.AddChild(headerRow); mainContainer.AddChild(ConnectionControlContainer); mainContainer.AddChild(buttonContainer); this.AddChild(mainContainer); BindSaveButtonHandlers(); BindBaudRateHandlers(); SetElementState(); } private void SetDisplayAttributes() { textImageButtonFactory.normalTextColor = RGBA_Bytes.White; textImageButtonFactory.hoverTextColor = RGBA_Bytes.White; textImageButtonFactory.disabledTextColor = RGBA_Bytes.White; textImageButtonFactory.pressedTextColor = RGBA_Bytes.White; textImageButtonFactory.borderWidth = 0; installButtonFactory.normalFillColor = ActiveTheme.Instance.PrimaryTextColor; installButtonFactory.normalTextColor = RGBA_Bytes.Black; installButtonFactory.borderWidth = 0; linkButtonFactory.textColor = RGBA_Bytes.White; linkButtonFactory.fontSize = 10; this.BackgroundColor = ActiveTheme.Instance.SecondaryBackgroundColor; this.AnchorAll(); this.Padding = new BorderDouble(0); //To be re-enabled once native borders are turned off } static int createCount = 0; void RecreateWidget(AfterUiArgs eventArgs) { // you can call this like this // AfterUiEvents.AddAction(new AfterUIAction(RecreateWidget)); createCount++; Parent.AddChild(new AddConnectionWidget((ConnectionWindow)Parent, Parent, ActivePrinter)); Parent.RemoveChild(this); } private void LoadSetupSettings(string make, string model) { Dictionary settingsDict = LoadPrinterSetupFromFile(make, model); //Determine if baud rate is needed and show controls if required string baudRate; if (settingsDict.TryGetValue("baud_rate", out baudRate)) { ActivePrinter.BaudRate = baudRate; editBaudRate = false; } else { editBaudRate = true; } //Determine if driver is needed and show install button as required string driverFile; installDriver = false; if (settingsDict.TryGetValue("windows_driver", out driverFile)) { string infPathAndFileToInstall = Path.Combine(ApplicationDataStorage.Instance.ApplicationStaticDataPath, "Drivers", driverFile); switch (MatterHackers.Agg.UI.WindowsFormsAbstract.GetOSType()) { case Agg.UI.WindowsFormsAbstract.OSType.Windows: if (File.Exists(infPathAndFileToInstall)) { installDriver = true; } break; default: break; } } } private Dictionary LoadPrinterSetupFromFile(string make, string model) { string setupSettingsPathAndFile = Path.Combine(ApplicationDataStorage.Instance.ApplicationStaticDataPath, "PrinterSettings", make, model, "setup.ini"); Dictionary settingsDict = new Dictionary(); if (System.IO.File.Exists(setupSettingsPathAndFile)) { try { string[] lines = System.IO.File.ReadAllLines(setupSettingsPathAndFile); foreach (string line in lines) { //Ignore commented lines if (!line.StartsWith("#")) { string[] settingLine = line.Split('='); string keyName = settingLine[0].Trim(); string settingDefaultValue = settingLine[1].Trim(); settingsDict.Add(keyName, settingDefaultValue); } } } catch { } } return settingsDict; } private void LoadPrinterSliceSettings(string make, string model) { string sliceSettingsPathAndFile = Path.Combine(ApplicationDataStorage.Instance.ApplicationStaticDataPath, "PrinterSettings", make, model, "config.ini"); if (System.IO.File.Exists(sliceSettingsPathAndFile)) { DataStorage.SliceSettingsCollection defaultCollection = new DataStorage.SliceSettingsCollection(); defaultCollection.Name = "__printer_default__"; SettingsLayer defaultSettingsLayer = ActiveSliceSettings.Instance.LoadConfigurationSettingsFromFile(sliceSettingsPathAndFile, defaultCollection); //Commit layer values foreach (KeyValuePair item in defaultSettingsLayer.settingsDictionary) { item.Value.Commit(); } } } private void SetElementState() { printerModelContainer.Visible = (this.ActivePrinter.Make != null); printerSerialPortContainer.Visible = (this.ActivePrinter.Model != null); if (editBaudRate) { printerBaudRateContainer.Visible = (this.ActivePrinter.Model != null); } else { printerBaudRateContainer.Visible = false; } if (installDriver) { printerDriverContainer.Visible = (this.ActivePrinter.Model != null); } else { printerDriverContainer.Visible = false; } } private FlowLayoutWidget createPrinterDriverContainer() { FlowLayoutWidget container = new FlowLayoutWidget(FlowDirection.TopToBottom); container.Margin = new BorderDouble(0, 5); BorderDouble elementMargin = new BorderDouble(top: 3); printerDriverInstallButton = installButtonFactory.Generate("Install Driver"); printerDriverInstallButton.Margin = new BorderDouble(0, 5); printerDriverMessage = new TextWidget("This printer requires a driver for communication.", 0, 0, 10); printerDriverMessage.TextColor = RGBA_Bytes.White; printerDriverMessage.HAnchor = HAnchor.ParentLeftRight; printerDriverMessage.Margin = elementMargin; container.AddChild(printerDriverMessage); container.AddChild(printerDriverInstallButton); container.HAnchor = HAnchor.ParentLeftRight; return container; } private FlowLayoutWidget createPrinterMakeContainer() { FlowLayoutWidget container = new FlowLayoutWidget(FlowDirection.TopToBottom); container.Margin = new BorderDouble(0, 5); BorderDouble elementMargin = new BorderDouble(top: 3); TextWidget printerManufacturerLabel = new TextWidget("Select Make:", 0, 0, 12); printerManufacturerLabel.TextColor = this.defaultTextColor; printerManufacturerLabel.HAnchor = HAnchor.ParentLeftRight; printerManufacturerLabel.Margin = elementMargin; PrinterChooser printerManufacturerSelector = new PrinterChooser(); printerManufacturerSelector.HAnchor = HAnchor.ParentLeftRight; printerManufacturerSelector.Margin = elementMargin; printerManufacturerSelector.ManufacturerDropList.SelectionChanged +=new EventHandler(ManufacturerDropList_SelectionChanged); printerMakeError = new TextWidget("Select the printer manufacturer", 0, 0, 10); printerMakeError.TextColor = RGBA_Bytes.White; printerMakeError.HAnchor = HAnchor.ParentLeftRight; printerMakeError.Margin = elementMargin; container.AddChild(printerManufacturerLabel); container.AddChild(printerManufacturerSelector); container.AddChild(printerMakeError); container.HAnchor = HAnchor.ParentLeftRight; return container; } private void ManufacturerDropList_SelectionChanged(object sender, EventArgs e) { ActivePrinter.Make = ((DropDownList)sender).SelectedValue; ActivePrinter.Model = null; //reconstruct model selector int currentIndex = ConnectionControlContainer.GetChildIndex(printerModelContainer); ConnectionControlContainer.RemoveChild(printerModelContainer); printerModelContainer = createPrinterModelContainer(ActivePrinter.Make); ConnectionControlContainer.AddChild(printerModelContainer, currentIndex); ConnectionControlContainer.Invalidate(); printerMakeError.Visible = false; SetElementState(); } private void ModelDropList_SelectionChanged(object sender, EventArgs e) { ActivePrinter.Model = ((DropDownList)sender).SelectedValue; LoadSetupSettings(ActivePrinter.Make, ActivePrinter.Model); printerModelError.Visible = false; SetElementState(); } private FlowLayoutWidget createPrinterModelContainer(string make = "Other") { FlowLayoutWidget container = new FlowLayoutWidget(FlowDirection.TopToBottom); container.Margin = new BorderDouble(0, 5); BorderDouble elementMargin = new BorderDouble(top: 3); TextWidget printerModelLabel = new TextWidget("Select Model:", 0, 0, 12); printerModelLabel.TextColor = this.defaultTextColor; printerModelLabel.HAnchor = HAnchor.ParentLeftRight; printerModelLabel.Margin = elementMargin; ModelChooser printerModelSelector = new ModelChooser(make); printerModelSelector.HAnchor = HAnchor.ParentLeftRight; printerModelSelector.Margin = elementMargin; printerModelSelector.ModelDropList.SelectionChanged += new EventHandler(ModelDropList_SelectionChanged); printerModelError = new TextWidget("Select the printer model", 0, 0, 10); printerModelError.TextColor = RGBA_Bytes.White; printerModelError.HAnchor = HAnchor.ParentLeftRight; printerModelError.Margin = elementMargin; container.AddChild(printerModelLabel); container.AddChild(printerModelSelector); container.AddChild(printerModelError); container.HAnchor = HAnchor.ParentLeftRight; return container; } private FlowLayoutWidget createPrinterBaudRateContainer() { FlowLayoutWidget container = new FlowLayoutWidget(FlowDirection.TopToBottom); container.Margin = new BorderDouble(0, 5); BorderDouble elementMargin = new BorderDouble(top: 3); TextWidget baudRateLabel = new TextWidget("Baud Rate:", 0, 0, 12); baudRateLabel.TextColor = this.defaultTextColor; baudRateLabel.Margin = new BorderDouble(0, 0, 0, 10); baudRateLabel.HAnchor = HAnchor.ParentLeftRight; baudRateWidget = GetBaudRateWidget(); baudRateWidget.HAnchor = HAnchor.ParentLeftRight; printerBaudRateError = new TextWidget("Select the baud rate", 0, 0, 10); printerBaudRateError.TextColor = RGBA_Bytes.White; printerBaudRateError.HAnchor = HAnchor.ParentLeftRight; printerBaudRateError.Margin = elementMargin; container.AddChild(baudRateLabel); container.AddChild(baudRateWidget); container.AddChild(printerBaudRateError); container.HAnchor = HAnchor.ParentLeftRight; return container; } private FlowLayoutWidget createPrinterNameContainer() { FlowLayoutWidget container = new FlowLayoutWidget(FlowDirection.TopToBottom); container.Margin = new BorderDouble(0, 5); BorderDouble elementMargin = new BorderDouble(top: 3); TextWidget printerNameLabel = new TextWidget("Printer Name:", 0, 0, 12); printerNameLabel.TextColor = this.defaultTextColor; printerNameLabel.HAnchor = HAnchor.ParentLeftRight; printerNameLabel.Margin = new BorderDouble(0, 0, 0, 1); printerNameInput = new MHTextEditWidget(this.ActivePrinter.Name); printerNameInput.HAnchor = HAnchor.ParentLeftRight; printerNameError = new TextWidget("Enter a printer name", 0, 0, 10); printerNameError.TextColor = RGBA_Bytes.White; printerNameError.HAnchor = HAnchor.ParentLeftRight; printerNameError.Margin = elementMargin; container.AddChild(printerNameLabel); container.AddChild(printerNameInput); container.AddChild(printerNameError); container.HAnchor = HAnchor.ParentLeftRight; return container; } private FlowLayoutWidget createPrinterSerialPortContainer() { FlowLayoutWidget container = new FlowLayoutWidget(FlowDirection.TopToBottom); container.Margin = new BorderDouble(0, 5); BorderDouble elementMargin = new BorderDouble(top: 3); comPortLabelWidget = new FlowLayoutWidget(); Button refreshComPorts = linkButtonFactory.Generate("refresh"); refreshComPorts.Click += new ButtonBase.ButtonEventHandler(RefreshComPorts); refreshComPorts.VAnchor = VAnchor.ParentCenter; TextWidget comPortLabel = new TextWidget("COM Port:", 0, 0, 12); comPortLabel.TextColor = this.defaultTextColor; comPortLabel.HAnchor = HAnchor.ParentLeftRight; comPortLabelWidget.AddChild(comPortLabel); comPortLabelWidget.AddChild(refreshComPorts); comPortLabelWidget.Margin = new BorderDouble(0, 0, 0, 10); comPortLabelWidget.HAnchor = HAnchor.ParentLeftRight; FlowLayoutWidget comPortContainer = new FlowLayoutWidget(FlowDirection.TopToBottom); comPortContainer.Margin = new BorderDouble(0); comPortContainer.HAnchor = HAnchor.ParentLeftRight; int portIndex = 0; foreach (string serialPort in SerialPort.GetPortNames()) { //Filter com port list based on usb type (applies to Mac mostly) bool looks_like_mac = serialPort.StartsWith("/dev/tty."); bool looks_like_pc = serialPort.StartsWith("COM"); if (looks_like_mac || looks_like_pc) { SerialPortIndexRadioButton comPortOption = createComPortOption(serialPort); comPortContainer.AddChild(comPortOption); portIndex++; } } //If there are no com ports in the filtered list assume we are missing something and show the unfiltered list if (portIndex == 0) { foreach (string serialPort in SerialPort.GetPortNames()) { SerialPortIndexRadioButton comPortOption = createComPortOption(serialPort); comPortContainer.AddChild(comPortOption); portIndex++; } } //If there are still no com ports show a message to that effect if (portIndex == 0) { TextWidget comPortOption = new TextWidget("No COM ports available"); comPortOption.Margin = new BorderDouble(3, 6, 5, 6); comPortOption.TextColor = this.subContainerTextColor; comPortContainer.AddChild(comPortOption); } printerComPortError = new TextWidget("Select the port", 0, 0, 10); printerComPortError.TextColor = RGBA_Bytes.White; printerComPortError.HAnchor = HAnchor.ParentLeftRight; printerComPortError.Margin = elementMargin; container.AddChild(comPortLabelWidget); container.AddChild(comPortContainer); container.AddChild(printerComPortError); container.HAnchor = HAnchor.ParentLeftRight; return container; } public GuiWidget GetBaudRateWidget() { FlowLayoutWidget baudRateContainer = new FlowLayoutWidget(FlowDirection.TopToBottom); baudRateContainer.Margin = new BorderDouble(0); //TO DO - Add handling for 'Other' option with attached TextEdit List baudRates = new List { "115200", "250000" }; BorderDouble baudRateMargin = new BorderDouble(3, 3, 5, 3); foreach (string baudRate in baudRates) { BaudRateRadioButton baudOption = new BaudRateRadioButton(baudRate); BaudRateButtonsList.Add(baudOption); baudOption.Margin = baudRateMargin; baudOption.TextColor = this.subContainerTextColor; if (this.ActivePrinter.BaudRate == baudRate) { baudOption.Checked = true; } baudRateContainer.AddChild(baudOption); } otherBaudRateRadioButton = new RadioButton("Other"); otherBaudRateRadioButton.Margin = baudRateMargin; otherBaudRateRadioButton.TextColor = this.subContainerTextColor; baudRateContainer.AddChild(otherBaudRateRadioButton); //See if the baud rate of the current print is in the list of displayed rates, //flag the 'other' option if it is not and prefill the rate. if (!baudRates.Contains(this.ActivePrinter.BaudRate.ToString())) { otherBaudRateRadioButton.Checked = true; otherBaudRateInput = new MHTextEditWidget(this.ActivePrinter.BaudRate.ToString()); //otherBaudRateInput.Visible = true; } else { otherBaudRateInput = new MHTextEditWidget(""); //otherBaudRateInput.Visible = false; } otherBaudRateInput.HAnchor = HAnchor.ParentLeftRight; baudRateContainer.AddChild(otherBaudRateInput); return baudRateContainer; } private void BindBaudRateHandlers() { otherBaudRateRadioButton.CheckedStateChanged += new RadioButton.CheckedStateChangedEventHandler(BindBaudRate_Select); foreach (BaudRateRadioButton button in BaudRateButtonsList) { button.CheckedStateChanged += new RadioButton.CheckedStateChangedEventHandler(BindBaudRate_Select); } BindBaudRate_Select(null, null); } private void BindBaudRate_Select(object sender, EventArgs e) { if (otherBaudRateRadioButton.Checked == true) { otherBaudRateInput.Visible = true; } else { otherBaudRateInput.Visible = false; } } public SerialPortIndexRadioButton createComPortOption(string serialPort) { //Add formatting here to make port names prettier string portName = serialPort; SerialPortIndexRadioButton comPortOption = new SerialPortIndexRadioButton(portName, serialPort); SerialPortButtonsList.Add(comPortOption); comPortOption.Margin = new BorderDouble(3, 3, 5, 3); comPortOption.TextColor = this.subContainerTextColor; if (this.ActivePrinter.ComPort == serialPort) { comPortOption.Checked = true; printerComExists = true; } return comPortOption; } void RefreshComPorts(object sender, MouseEventArgs mouseEvent) { try { this.ActivePrinter.Name = printerNameInput.Text; this.ActivePrinter.BaudRate = GetSelectedBaudRate(); this.ActivePrinter.ComPort = GetSelectedSerialPort(); } catch { } this.windowController.ChangedToEditPrinter(this.ActivePrinter); } void ReloadCurrentWidget(object sender, MouseEventArgs mouseEvent) { if (this.addNewPrinterFlag == true) { this.windowController.ChangeToAddPrinter(); } else { this.windowController.ChangedToEditPrinter(this.ActivePrinter); } } void BindSaveButtonHandlers() { saveButton.UnbindClickEvents(); saveButton.Text = "Save"; saveButton.Enabled = true; saveButton.Click += new ButtonBase.ButtonEventHandler(SaveButton_Click); } void CloseWindow(object o, MouseEventArgs e) { PrinterCommunication.Instance.HaltConnectionThread(); this.containerWindowToClose.Close(); } void CancelButton_Click(object sender, MouseEventArgs mouseEvent) { if (GetPrinterRecordCount() > 0) { this.windowController.ChangeToChoosePrinter(); } else { this.containerWindowToClose.Close(); } } void SaveButton_Click(object sender, MouseEventArgs mouseEvent) { this.ActivePrinter.Name = printerNameInput.Text; try { this.ActivePrinter.BaudRate = GetSelectedBaudRate(); this.ActivePrinter.ComPort = GetSelectedSerialPort(); } catch { //Unable to retrieve Baud or Port, possibly because they weren't shown as options - needs better handling } this.ActivePrinter.Commit(); this.windowController.ChangeToChoosePrinter(); } private string GetSelectedBaudRate() { foreach (BaudRateRadioButton button in BaudRateButtonsList) { if (button.Checked) { return button.BaudRate.ToString(); } } if (otherBaudRateRadioButton.Checked) { return otherBaudRateInput.Text; } throw new Exception("Could not find a selected button."); } void InstallDriver(string fileName) { string systemFolder = Environment.GetFolderPath(System.Environment.SpecialFolder.System); string pathToDriver = Path.Combine(systemFolder, "DriverStore", "FileRepository"); foreach (string directory in Directory.EnumerateDirectories(pathToDriver)) { if (directory.ToUpper().Contains("REPLICATOR.INF")) { int a = 0; } } string infPathAndFileToInstall = string.Format("/data/Drivers/{0}", fileName); switch (MatterHackers.Agg.UI.WindowsFormsAbstract.GetOSType()) { case Agg.UI.WindowsFormsAbstract.OSType.Windows: if (!File.Exists(infPathAndFileToInstall)) { var driverInstallerProcess = new Process(); // Prepare the process to run // Enter in the command line arguments, everything you would enter after the executable name itself driverInstallerProcess.StartInfo.Arguments = "--installInf \"" + infPathAndFileToInstall; // Enter the executable to run, including the complete path string printerDriverInstallerExePathAndFileName = Path.Combine(".", "PrinterDriverInstaller.exe"); driverInstallerProcess.StartInfo.CreateNoWindow = true; driverInstallerProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; driverInstallerProcess.StartInfo.FileName = System.IO.Path.GetFullPath(printerDriverInstallerExePathAndFileName); driverInstallerProcess.StartInfo.Verb = "runas"; driverInstallerProcess.StartInfo.UseShellExecute = true; driverInstallerProcess.Start(); driverInstallerProcess.WaitForExit(); // Retrieve the app's exit code var exitCode = driverInstallerProcess.ExitCode; } break; case Agg.UI.WindowsFormsAbstract.OSType.Mac: break; } } private string GetSelectedSerialPort() { foreach (SerialPortIndexRadioButton button in SerialPortButtonsList) { if (button.Checked) { return button.PortValue; } } throw new Exception("Could not find a selected button."); } } }