Index: trunk/src/tools/win/ChromeDebug/ChromeDebug/AttachDialog.cs |
=================================================================== |
--- trunk/src/tools/win/ChromeDebug/ChromeDebug/AttachDialog.cs (revision 223795) |
+++ trunk/src/tools/win/ChromeDebug/ChromeDebug/AttachDialog.cs (working copy) |
@@ -1,250 +0,0 @@ |
-using System; |
-using System.Collections.Generic; |
-using System.ComponentModel; |
-using System.Data; |
-using System.Diagnostics; |
-using System.Drawing; |
-using System.IO; |
-using System.Linq; |
-using System.Management; |
-using System.Text; |
-using System.Threading.Tasks; |
-using System.Windows.Forms; |
- |
-using ChromeDebug.LowLevel; |
- |
-namespace ChromeDebug { |
- // The form that is displayed to allow the user to select processes to attach to. Note that we |
- // cannot interact with the DTE object from here (I assume this is because the dialog is running |
- // on a different thread, although I don't fully understand), so any access to the DTE object |
- // will have to be done through events that get posted back to the main package thread. |
- public partial class AttachDialog : Form { |
- private class ProcessViewItem : ListViewItem { |
- public ProcessViewItem() { |
- Category = ProcessCategory.Other; |
- MachineType = LowLevelTypes.MachineType.UNKNOWN; |
- } |
- |
- public string Exe; |
- public int ProcessId; |
- public int SessionId; |
- public string Title; |
- public string DisplayCmdLine; |
- public string[] CmdLineArgs; |
- public ProcessCategory Category; |
- public LowLevelTypes.MachineType MachineType; |
- |
- public ProcessDetail Detail; |
- } |
- |
- private Dictionary<ProcessCategory, List<ProcessViewItem>> loadedProcessTable = null; |
- private Dictionary<ProcessCategory, ListViewGroup> processGroups = null; |
- private List<int> selectedProcesses = null; |
- |
- public AttachDialog() { |
- InitializeComponent(); |
- |
- loadedProcessTable = new Dictionary<ProcessCategory, List<ProcessViewItem>>(); |
- processGroups = new Dictionary<ProcessCategory, ListViewGroup>(); |
- selectedProcesses = new List<int>(); |
- |
- // Create and initialize the groups and process lists only once. On a reset |
- // we don't clear the groups manually, clearing the list view should clear the |
- // groups. And we don't clear the entire processes_ dictionary, only the |
- // individual buckets inside the dictionary. |
- foreach (object value in Enum.GetValues(typeof(ProcessCategory))) { |
- ProcessCategory category = (ProcessCategory)value; |
- |
- ListViewGroup group = new ListViewGroup(category.ToGroupTitle()); |
- processGroups[category] = group; |
- listViewProcesses.Groups.Add(group); |
- |
- loadedProcessTable[category] = new List<ProcessViewItem>(); |
- } |
- } |
- |
- // Provides an iterator that evaluates to the process ids of the entries that are selected |
- // in the list view. |
- public IEnumerable<int> SelectedItems { |
- get { |
- foreach (ProcessViewItem item in listViewProcesses.SelectedItems) |
- yield return item.ProcessId; |
- } |
- } |
- |
- private void AttachDialog_Load(object sender, EventArgs e) { |
- RepopulateListView(); |
- } |
- |
- // Remove command line arguments that we aren't interested in displaying as part of the command |
- // line of the process. |
- private string[] FilterCommandLine(string[] args) { |
- Func<string, int, bool> AllowArgument = delegate(string arg, int index) { |
- if (index == 0) |
- return false; |
- return !arg.StartsWith("--force-fieldtrials", StringComparison.CurrentCultureIgnoreCase); |
- }; |
- |
- // The force-fieldtrials command line option makes the command line view useless, so remove |
- // it. Also remove args[0] since that is the process name. |
- args = args.Where(AllowArgument).ToArray(); |
- return args; |
- } |
- |
- private void ReloadNativeProcessInfo() { |
- foreach (List<ProcessViewItem> list in loadedProcessTable.Values) { |
- list.Clear(); |
- } |
- |
- Process[] processes = Process.GetProcesses(); |
- foreach (Process p in processes) { |
- ProcessViewItem item = new ProcessViewItem(); |
- try { |
- item.Detail = new ProcessDetail(p.Id); |
- if (item.Detail.CanReadPeb && item.Detail.CommandLine != null) { |
- item.CmdLineArgs = Utility.SplitArgs(item.Detail.CommandLine); |
- item.DisplayCmdLine = GetFilteredCommandLineString(item.CmdLineArgs); |
- } |
- item.MachineType = item.Detail.MachineType; |
- } |
- catch (Exception) { |
- // Generally speaking, an exception here means the process is privileged and we cannot |
- // get any information about the process. For those processes, we will just display the |
- // information that the Framework gave us in the Process structure. |
- } |
- |
- // If we don't have the machine type, its privilege level is high enough that we won't be |
- // able to attach a debugger to it anyway, so skip it. |
- if (item.MachineType == LowLevelTypes.MachineType.UNKNOWN) |
- continue; |
- |
- item.ProcessId = p.Id; |
- item.SessionId = p.SessionId; |
- item.Title = p.MainWindowTitle; |
- item.Exe = p.ProcessName; |
- if (item.CmdLineArgs != null) |
- item.Category = DetermineProcessCategory(item.CmdLineArgs); |
- |
- List<ProcessViewItem> items = loadedProcessTable[item.Category]; |
- item.Group = processGroups[item.Category]; |
- items.Add(item); |
- } |
- } |
- |
- // Filter the command line arguments to remove extraneous arguments that we don't wish to |
- // display. |
- private string GetFilteredCommandLineString(string[] args) { |
- if (args == null || args.Length == 0) |
- return string.Empty; |
- |
- args = FilterCommandLine(args); |
- return string.Join(" ", args, 0, args.Length); |
- } |
- |
- // Using a heuristic based on the command line, tries to determine what type of process this |
- // is. |
- private ProcessCategory DetermineProcessCategory(string[] cmdline) { |
- if (cmdline == null || cmdline.Length == 0) |
- return ProcessCategory.Other; |
- |
- string file = Path.GetFileName(cmdline[0]); |
- if (file.Equals("delegate_execute.exe", StringComparison.CurrentCultureIgnoreCase)) |
- return ProcessCategory.DelegateExecute; |
- else if (file.Equals("chrome.exe", StringComparison.CurrentCultureIgnoreCase)) { |
- if (cmdline.Contains("--type=renderer")) |
- return ProcessCategory.Renderer; |
- else if (cmdline.Contains("--type=plugin") || cmdline.Contains("--type=ppapi")) |
- return ProcessCategory.Plugin; |
- else if (cmdline.Contains("--type=gpu-process")) |
- return ProcessCategory.Gpu; |
- else if (cmdline.Contains("--type=service")) |
- return ProcessCategory.Service; |
- else if (cmdline.Any(arg => arg.StartsWith("-ServerName"))) |
- return ProcessCategory.MetroViewer; |
- else |
- return ProcessCategory.Browser; |
- } else |
- return ProcessCategory.Other; |
- } |
- |
- private void InsertCategoryItems(ProcessCategory category) { |
- foreach (ProcessViewItem item in loadedProcessTable[category]) { |
- item.SubItems.Add(item.Exe); |
- item.SubItems.Add(item.ProcessId.ToString()); |
- item.SubItems.Add(item.Title); |
- item.SubItems.Add(item.MachineType.ToString()); |
- item.SubItems.Add(item.SessionId.ToString()); |
- item.SubItems.Add(item.DisplayCmdLine); |
- listViewProcesses.Items.Add(item); |
- } |
- } |
- |
- private void AutoResizeColumns() { |
- // First adjust to the width of the headers, since it's fast. |
- listViewProcesses.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize); |
- |
- // Save the widths so we can use them again later. |
- List<int> widths = new List<int>(); |
- foreach (ColumnHeader header in listViewProcesses.Columns) |
- widths.Add(header.Width); |
- |
- // Now let Windows do the slow adjustment based on the content. |
- listViewProcesses.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent); |
- |
- // Finally, iterate over each column, and resize those columns that just got smaller. |
- listViewProcesses.Columns[0].Width = 0; |
- int total = 0; |
- for (int i = 1; i < listViewProcesses.Columns.Count; ++i) { |
- // Resize to the largest of the two, but don't let it go over a pre-defined maximum. |
- int max = Math.Max(listViewProcesses.Columns[i].Width, widths[i]); |
- int capped = Math.Min(max, 300); |
- |
- // We do still want to fill up the available space in the list view however, so if we're |
- // under then we can fill. |
- int globalMinWidth = listViewProcesses.Width - SystemInformation.VerticalScrollBarWidth; |
- if (i == listViewProcesses.Columns.Count - 1 && (total + capped) < (globalMinWidth - 4)) |
- capped = globalMinWidth - total - 4; |
- |
- total += capped; |
- listViewProcesses.Columns[i].Width = capped; |
- } |
- } |
- |
- private void RepopulateListView() { |
- listViewProcesses.Items.Clear(); |
- |
- ReloadNativeProcessInfo(); |
- |
- InsertCategoryItems(ProcessCategory.Browser); |
- InsertCategoryItems(ProcessCategory.Renderer); |
- InsertCategoryItems(ProcessCategory.Gpu); |
- InsertCategoryItems(ProcessCategory.Plugin); |
- InsertCategoryItems(ProcessCategory.MetroViewer); |
- InsertCategoryItems(ProcessCategory.Service); |
- InsertCategoryItems(ProcessCategory.DelegateExecute); |
- if (!checkBoxOnlyChrome.Checked) |
- InsertCategoryItems(ProcessCategory.Other); |
- |
- AutoResizeColumns(); |
- } |
- |
- private void buttonRefresh_Click(object sender, EventArgs e) { |
- RepopulateListView(); |
- } |
- |
- private void buttonAttach_Click(object sender, EventArgs e) { |
- System.Diagnostics.Debug.WriteLine("Closing dialog."); |
- this.Close(); |
- } |
- |
- private void checkBoxOnlyChrome_CheckedChanged(object sender, EventArgs e) { |
- if (!checkBoxOnlyChrome.Checked) |
- InsertCategoryItems(ProcessCategory.Other); |
- else { |
- foreach (ProcessViewItem item in loadedProcessTable[ProcessCategory.Other]) { |
- listViewProcesses.Items.Remove(item); |
- } |
- } |
- } |
- } |
-} |