private Process m_process; // The running process public BufferedProcess(LaunchApp launch) : base(launch.OutputFilepath, launch.AppendOutputFile) { m_launch = launch; m_outbuf = new byte[BufBlockSize]; m_errbuf = new byte[BufBlockSize]; // Create the process ProcessStartInfo info = new ProcessStartInfo { UseShellExecute = false, RedirectStandardOutput = launch.CaptureStdout, RedirectStandardError = launch.CaptureStderr, CreateNoWindow = !launch.ShowWindow, FileName = launch.Executable, Arguments = launch.Arguments, WorkingDirectory = launch.WorkingDirectory }; m_process = new Process { StartInfo = info }; m_process.Exited += (s, a) => { Log.Write(ELogLevel.Info, $"Process {launch.Executable} exited"); RaiseConnectionDropped(); }; }
public LaunchApp(LaunchApp rhs) { Executable = rhs.Executable; Arguments = rhs.Arguments; WorkingDirectory = rhs.WorkingDirectory; OutputFilepath = rhs.OutputFilepath; ShowWindow = rhs.ShowWindow; AppendOutputFile = rhs.AppendOutputFile; Streams = rhs.Streams; }
/// <summary>Launch a process, piping its output into a temporary file</summary> private void LaunchProcess(LaunchApp conn) { Debug.Assert(conn != null); BufferedProcess buffered_process = null; try { // Close any currently open file // Strictly, we don't have to close because OpenLogFile closes before opening // however if the user reopens the same process the existing process will hold // a lock to the capture file preventing the new process being created. Src = null; // Set options so that data always shows PrepareForStreamedData(conn.OutputFilepath); // Launch the process with standard output/error redirected to the temporary file buffered_process = new BufferedProcess(conn); // Give some UI feedback when the process ends buffered_process.ConnectionDropped += (s, a) => { this.BeginInvoke(() => SetStaticStatusMessage(string.Format("{0} exited", Path.GetFileName(conn.Executable)), Color.Black, Color.LightSalmon)); }; // Open the capture file created by buffered_process OpenSingleLogFile(buffered_process.Filepath, !buffered_process.TmpFile); buffered_process.Start(); SetStaticStatusMessage("Connected", Color.Black, Color.LightGreen); // Pass over the ref if (m_buffered_process != null) { m_buffered_process.Dispose(); } m_buffered_process = buffered_process; buffered_process = null; } catch (Exception ex) { Log.Write(ELogLevel.Error, ex, $"Failed to launch child process {conn.Executable} {conn.Arguments} -> {conn.OutputFilepath}"); Misc.ShowMessage(this, $"Failed to launch child process {conn.Executable}.", Application.ProductName, MessageBoxIcon.Error, ex); } finally { if (buffered_process != null) { buffered_process.Dispose(); } } }
public Settings() { RecentFiles = string.Empty; RecentPatternSets = string.Empty; Font = new Font("Consolas", 8.25f, GraphicsUnit.Point); RestoreScreenLoc = false; // False so that first runs start in the default window position ScreenPosition = new Point(100, 100); WindowSize = new Size(640, 480); PatternSetDirectory = Util.ResolveUserDocumentsPath(Application.CompanyName, Application.ProductName); ExportFilepath = null; AlternateLineColours = true; LineSelectBackColour = Color.DarkGreen; LineSelectForeColour = Color.White; LineBackColour1 = Color.WhiteSmoke; LineBackColour2 = Color.White; LineForeColour1 = Color.Black; LineForeColour2 = Color.Black; FileScrollWidth = Constants.FileScrollWidthDefault; ScrollBarFileRangeColour = Color.FromArgb(0x80, Color.White); ScrollBarCachedRangeColour = Color.FromArgb(0x40, Color.LightBlue); ScrollBarDisplayRangeColour = Color.FromArgb(0x80, Color.SteelBlue); BookmarkColour = Color.Violet; RowHeight = Constants.RowHeightDefault; LoadLastFile = false; LastLoadedFile = string.Empty; OpenAtEnd = true; FullPathInTitle = true; TabSizeInSpaces = 4; FileChangesAdditive = true; IgnoreBlankLines = false; AlwaysOnTop = false; FirstRun = true; ShowTOTD = true; CheckForUpdates = false; CheckForUpdatesServer = "http://www.rylogic.co.nz/"; UseWebProxy = false; WebProxyHost = string.Empty; WebProxyPort = Constants.PortNumberWebProxyDefault; QuickFilterEnabled = false; HighlightsEnabled = true; FiltersEnabled = false; TransformsEnabled = false; ActionsEnabled = false; TailEnabled = true; WatchEnabled = true; FileBufSize = Constants.FileBufSizeDefault; MaxLineLength = Constants.MaxLineLengthDefault; LineCacheCount = Constants.LineCacheCountDefault; Patterns = PatternSet.Default(); RowDelimiter = string.Empty; // stored in humanised form, empty means auto detect ColDelimiter = string.Empty; // stored in humanised form, empty means auto detect ColumnCount = 2; Encoding = string.Empty; // empty means auto detect OutputFilepathHistory = new string[0]; LogProgramOutputHistory = new LaunchApp[0]; NetworkConnectionHistory = new NetConn[0]; SerialConnectionHistory = new SerialConn[0]; PipeConnectionHistory = new PipeConn[0]; AndroidLogcat = new AndroidLogcat(); AutoSaveOnChanges = true; }
public ProgramOutputUI(Settings settings) { InitializeComponent(); m_settings = settings; m_outp_history = new List <string>(m_settings.OutputFilepathHistory); Launch = m_settings.LogProgramOutputHistory.Length != 0 ? new LaunchApp(m_settings.LogProgramOutputHistory[0]) : new LaunchApp(); m_tt = new ToolTip(); // Command line m_combo_launch_cmdline.ToolTip(m_tt, "Command line for the application to launch"); m_combo_launch_cmdline.Load(m_settings.LogProgramOutputHistory); m_combo_launch_cmdline.TextChanged += (s, a) => { Launch.Executable = m_combo_launch_cmdline.Text; UpdateUI(); }; m_combo_launch_cmdline.SelectedIndexChanged += (s, a) => { Launch = new LaunchApp((LaunchApp)m_combo_launch_cmdline.SelectedItem); UpdateUI(); }; // Arguments m_edit_arguments.ToolTip(m_tt, "Command line arguments for the executable"); m_edit_arguments.Text = Launch.Arguments; m_edit_arguments.TextChanged += (s, a) => { if (!((TextBox)s).Modified) { return; } Launch.Arguments = m_edit_arguments.Text; UpdateUI(); }; // Working Directory m_edit_working_dir.ToolTip(m_tt, "The application working directory"); m_edit_working_dir.Text = Launch.WorkingDirectory; m_edit_working_dir.TextChanged += (s, a) => { if (!((TextBox)s).Modified) { return; } Launch.WorkingDirectory = m_edit_working_dir.Text; UpdateUI(); }; // Output file m_combo_output_filepath.ToolTip(m_tt, "The file to save captured program output in.\r\nLeave blank to not save captured output"); foreach (var i in m_outp_history) { m_combo_output_filepath.Items.Add(i); } m_combo_output_filepath.Text = Launch.OutputFilepath; m_combo_output_filepath.TextChanged += (s, a) => { Launch.OutputFilepath = m_combo_output_filepath.Text; UpdateUI(); }; // Browse executable m_btn_browse_exec.Click += (s, a) => { var dg = new OpenFileDialog { Filter = Constants.ExecutablesFilter, CheckFileExists = true }; if (dg.ShowDialog(this) != DialogResult.OK) { return; } Launch.Executable = dg.FileName; Launch.WorkingDirectory = Path.GetDirectoryName(dg.FileName); UpdateUI(); }; // Browse output file m_btn_browse_output.Click += (s, a) => { var dg = new SaveFileDialog { Filter = Constants.LogFileFilter, CheckPathExists = true, OverwritePrompt = false }; if (dg.ShowDialog(this) != DialogResult.OK) { return; } Launch.OutputFilepath = dg.FileName; UpdateUI(); }; // Todo, show window doesn't really work, remove it Launch.ShowWindow = false; //// Show window //m_check_show_window.ToolTip(m_tt, "If checked, the window for the application is shown.\r\n If not, then it is hidden"); //m_check_show_window.Checked = Launch.ShowWindow; //m_check_show_window.Click += (s,a)=> // { // Launch.ShowWindow = m_check_show_window.Checked; // UpdateUI(); // }; // Append to existing m_check_append.ToolTip(m_tt, "If checked, captured output is appended to the capture file.\r\nIf not, then the capture file is overwritten"); m_check_append.Checked = Launch.AppendOutputFile; m_check_append.Click += (s, a) => { Launch.AppendOutputFile = m_check_append.Checked; UpdateUI(); }; // Capture Stdout m_check_capture_stdout.ToolTip(m_tt, "Check to log standard output (STDOUT)"); m_check_capture_stdout.Click += (s, a) => { Launch.Streams = (StandardStreams)Bit.SetBits( (int)Launch.Streams, (int)StandardStreams.Stdout, m_check_capture_stdout.Checked); }; // Capture Stderr m_check_capture_stderr.ToolTip(m_tt, "Check to log standard error (STDERR)"); m_check_capture_stderr.Click += (s, a) => { Launch.Streams = (StandardStreams)Bit.SetBits( (int)Launch.Streams, (int)StandardStreams.Stderr, m_check_capture_stdout.Checked); }; // Save settings on close FormClosing += (s, a) => { // If launch is selected, add the launch command line to the history if (DialogResult == DialogResult.OK && Launch.Executable.Length != 0) { m_settings.LogProgramOutputHistory = Util.AddToHistoryList(m_settings.LogProgramOutputHistory, Launch, true, Constants.MaxProgramHistoryLength); } }; Disposed += (s, a) => { m_tt.Dispose(); }; UpdateUI(); }
public AndroidLogcatUI(Settings settings) { InitializeComponent(); m_tt = new ToolTip(); m_settings = new AndroidLogcat(settings.AndroidLogcat); m_device_list = new BindingList <string>(); m_bs_device_list = new BindingSource { DataSource = m_device_list }; m_filterspecs = new BindingList <AndroidLogcat.FilterSpec>(m_settings.FilterSpecs.ToList()); var output_filepaths = settings.OutputFilepathHistory; Launch = new LaunchApp(); PreferredDevice = m_settings.SelectedDevice; const string prompt_text = "<Please set the path to adb.exe>"; m_edit_adb_fullpath.ToolTip(m_tt, "The full path to the android debug bridge executable ('adb.exe')"); m_edit_adb_fullpath.Text = prompt_text; m_edit_adb_fullpath.ForeColor = Color.LightGray; m_edit_adb_fullpath.GotFocus += (s, a) => { if (m_edit_adb_fullpath.ForeColor != Color.LightGray) { return; } m_edit_adb_fullpath.Text = string.Empty; m_edit_adb_fullpath.ForeColor = Color.Black; }; m_edit_adb_fullpath.LostFocus += (s, a) => { if (m_edit_adb_fullpath.Text.HasValue()) { return; } m_edit_adb_fullpath.ForeColor = Color.LightGray; m_edit_adb_fullpath.Text = prompt_text; }; m_edit_adb_fullpath.TextChanged += (s, a) => { if (!((TextBox)s).Modified) { return; } SetAdbPath(m_edit_adb_fullpath.Text); }; // The version info printed by adb UpdateAdbVersionInfo(false); // Browse for the adb path m_btn_browse_adb.ToolTip(m_tt, "Browse the file system for the android debug bridge executable ('adb.exe')"); m_btn_browse_adb.Click += (s, a) => { var dlg = new OpenFileDialog { Filter = "Programs (*.exe)|*.exe", FileName = "adb.exe" }; if (dlg.ShowDialog(this) != DialogResult.OK) { return; } SetAdbPath(dlg.FileName); }; m_btn_browse_adb.Focus(); // Devices list m_listbox_devices.ToolTip(m_tt, "The android devices current connected to adb. Hit 'Refresh' to repopulate this list"); m_listbox_devices.DataSource = m_bs_device_list; m_bs_device_list.CurrentChanged += (s, a) => { UpdateAdbCommand(); SelectPreferredOutputFile(); m_btn_ok.Enabled = m_bs_device_list.CurrentOrDefault() != null; }; // Connect button m_btn_connect.ToolTip(m_tt, "Add an android device not currently shown in the 'Connected Devices' list"); m_btn_connect.Click += (s, a) => ConnectDevice(); m_btn_connect.Enabled = false; // Until a valid adb path is set // Log buffers (main and system by default) m_listbox_log_buffers.ToolTip(m_tt, "The android log buffers to output"); m_listbox_log_buffers.DataSource = Enum.GetNames(typeof(AndroidLogcat.ELogBuffer)).Select(x => x.ToLowerInvariant()).ToArray(); foreach (var x in m_settings.LogBuffers) { m_listbox_log_buffers.SetSelected((int)x, true); } m_listbox_log_buffers.SelectedIndexChanged += (s, a) => UpdateAdbCommand(); // Filter specs m_grid_filterspec.ToolTip(m_tt, "Configure filters to apply to the logcat output. Tag = '*' applies the filter to all log entries"); m_grid_filterspec.AutoGenerateColumns = false; m_grid_filterspec.Columns.Add(new DataGridViewTextBoxColumn { DataPropertyName = nameof(AndroidLogcat.FilterSpec.Tag) }); m_grid_filterspec.Columns.Add(new DataGridViewComboBoxColumn { DataPropertyName = nameof(AndroidLogcat.FilterSpec.Priority), DataSource = Enum.GetValues(typeof(AndroidLogcat.EFilterPriority)), Sorted = false }); m_grid_filterspec.DataSource = m_filterspecs; m_filterspecs.ListChanged += (s, a) => UpdateAdbCommand(); // Log format m_combo_log_format.ToolTip(m_tt, "Select the format of the log output"); m_combo_log_format.DataSource = Enum.GetNames(typeof(AndroidLogcat.ELogFormat)).Select(x => x.ToLowerInvariant()).ToArray(); m_combo_log_format.SelectedIndex = (int)m_settings.LogFormat; m_combo_log_format.SelectedIndexChanged += (s, a) => UpdateAdbCommand(); // Capture log output m_check_capture_to_log.ToolTip(m_tt, "Enable capturing the logcat output to a file"); m_check_capture_to_log.Checked = m_settings.CaptureOutputToFile; m_check_capture_to_log.CheckedChanged += (s, a) => { m_combo_output_file.Enabled = m_check_capture_to_log.Checked; m_btn_browse_output_file.Enabled = m_check_capture_to_log.Checked; m_check_append.Enabled = m_check_capture_to_log.Checked; }; // Log out capture file m_combo_output_file.ToolTip(m_tt, "The file path to save captured logcat output to"); m_combo_output_file.Load(output_filepaths); m_combo_output_file.Enabled = m_check_capture_to_log.Checked; // Browse for capture output file m_btn_browse_output_file.ToolTip(m_tt, "Browse the file system for the file to write logcat output to"); m_btn_browse_output_file.Enabled = m_check_capture_to_log.Checked; m_btn_browse_output_file.Click += (s, a) => { var dlg = new OpenFileDialog(); if (dlg.ShowDialog(this) != DialogResult.OK) { return; } m_combo_output_file.Items.Insert(0, dlg.FileName); m_combo_output_file.SelectedIndex = 0; }; // Append to existing m_check_append.ToolTip(m_tt, "If checked, captured output is appended to the capture file.\r\nIf not, then the capture file is overwritten"); m_check_append.Checked = Launch.AppendOutputFile; m_check_append.Enabled = m_check_capture_to_log.Checked; // Refresh button m_btn_refresh.ToolTip(m_tt, "Repopulate this dialog with data collected using adb.exe"); m_btn_refresh.Click += (s, a) => PopulateUsingAdb(); // Reset adb button m_btn_resetadb.ToolTip(m_tt, "Restart the adb server process.\r\nCan solve problems when connecting to devices"); m_btn_resetadb.Enabled = false; // unless there is an adb path m_btn_resetadb.Click += (s, a) => { var adbs = Process.GetProcessesByName("adb"); foreach (var adb in adbs) { adb.Kill(); } Adb("start-server"); PopulateUsingAdb(); }; // Ok button m_btn_ok.Enabled = m_listbox_devices.SelectedItem != null; Load += (s, a) => { AutoDetectAdbPath(); }; // Save settings on close FormClosing += (s, a) => { // If launch is selected, add the launch command line to the history if (DialogResult == DialogResult.OK) { // Cancelled until we're sure we have a valid launch command DialogResult = DialogResult.Cancel; // Save settings - Only save here, so that cancel causes settings to be unchanged m_settings.AdbFullPath = m_edit_adb_fullpath.Text; m_settings.CaptureOutputToFile = m_check_capture_to_log.Checked; m_settings.AppendOutputFile = m_check_append.Checked; m_settings.LogBuffers = m_listbox_log_buffers.SelectedIndices.Cast <AndroidLogcat.ELogBuffer>().ToArray(); m_settings.FilterSpecs = m_filterspecs.ToArray(); m_settings.LogFormat = (AndroidLogcat.ELogFormat)m_combo_log_format.SelectedIndex; m_settings.SelectedDevice = m_listbox_devices.SelectedItem.ToString(); settings.AndroidLogcat = m_settings; settings.RowDelimiter = "<CR><CR><LF>"; // Use cancelled if no device was selected or no valid adb path found if (ValidAdbPath && m_listbox_devices.SelectedItem != null) { string exe, args; GenerateAdbCommand(out exe, out args); // Update the launch options Launch.Executable = exe; Launch.Arguments = args; Launch.WorkingDirectory = Path.GetDirectoryName(exe) ?? string.Empty; Launch.OutputFilepath = m_settings.CaptureOutputToFile ? m_combo_output_file.Text : string.Empty; Launch.ShowWindow = false; Launch.AppendOutputFile = m_check_append.Checked; Launch.Streams = StandardStreams.Stdout | StandardStreams.Stderr; DialogResult = DialogResult.OK; } } // If the adb full path has changed, update the settings even if DialogResult == cancel else if (ValidAdbPath && settings.AndroidLogcat.AdbFullPath != m_edit_adb_fullpath.Text) { var save = new AndroidLogcat(settings.AndroidLogcat); save.AdbFullPath = m_edit_adb_fullpath.Text; settings.AndroidLogcat = save; } }; Disposed += (s, a) => { m_tt.Dispose(); }; }