public CloseableTabItem GetTabItem() { int iTabItemIndex = 0; //first we need to see if there is already an existing one, then close it // need to give it a chance to clean up, so invoke the CloseTabItem Method foreach (TabItem tabitem in _perfGraphToolWindowControl.TabControl.Items) { if (tabitem.Name == Path.GetFileNameWithoutExtension(_FileToExecute)) { // problem: each time asm is recompiled/reloaed, the type "CloseableTabItem" has different identity, so casting can cause error in this case // so need to call via reflection if (tabitem.GetType().Name == "CloseableTabItem") { // found an existing one. Need to close it tabitem.GetType().GetMethod("CloseTabItem").Invoke(tabitem, null); //tabItemTabProc = (CloseableTabItem)tabitem; // this throws invalid cast exception if recompiled //tabItemTabProc.CloseTabItem(); break; } } iTabItemIndex++; } var tabItemTabProc = new CloseableTabItem(Path.GetFileNameWithoutExtension(_FileToExecute), string.Empty); _perfGraphToolWindowControl.TabControl.Items.Add(tabItemTabProc); _perfGraphToolWindowControl.TabControl.SelectedIndex = _perfGraphToolWindowControl.TabControl.Items.Count - 1; // select User output tab return(tabItemTabProc); }
public MyCloseButton(CloseableTabItem closeableTabItem) { this._closeableTabItem = closeableTabItem; Background = Brushes.Transparent; Height = 10; VerticalAlignment = VerticalAlignment.Top; tbClose = new TextBlock() { Text = "r", IsEnabled = false, FontFamily = new FontFamily("Marlett"), FontSize = 8, VerticalAlignment = VerticalAlignment.Top, Background = Brushes.Transparent, }; this.Content = tbClose; }
async Task InitializeAsync() { await Task.Yield(); var strxaml = $@"<Grid xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" xmlns:l=""clr-namespace:{this.GetType().Namespace};assembly={ System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().Location)}"" > <Grid.RowDefinitions> <RowDefinition Height=""auto""/> <RowDefinition Height=""*""/> </Grid.RowDefinitions> <StackPanel Grid.Row=""0"" HorizontalAlignment=""Left"" Height=""25"" VerticalAlignment=""Top"" Orientation=""Horizontal""> <CheckBox Margin=""15,0,0,10"" Content=""OutputPane"" IsChecked=""{{Binding UseOutputPane}}"" ToolTip=""Output to Debug OutputPane 'PerfGraphVSIX'""/> <CheckBox Margin=""15,0,0,10"" Content=""ShowAllProperties"" IsChecked=""{{Binding ShowAllProperties}}"" ToolTip=""Show the properties of the Telemetry event""/> <Label Content=""Filter""/> <TextBox Text=""{{Binding EventFilter}}"" Width =""200"" ToolTip=""Filter the events""/> <Button Name=""btnUpdateFilter"" Content=""UpdateFilter"" Background=""LightGray""/> </StackPanel> <Grid Name=""gridUser"" Grid.Row = ""1""> </Grid> </Grid> "; var strReader = new System.IO.StringReader(strxaml); var xamlreader = XmlReader.Create(strReader); var grid = (Grid)(XamlReader.Load(xamlreader)); CloseableTabItem tabItemTabProc = GetTabItem(); tabItemTabProc.Content = grid; grid.DataContext = this; var gridUser = (Grid)grid.FindName("gridUser"); var btnUpdateFilter = (Button)grid.FindName("btnUpdateFilter"); var outputPane = await GetOutputPaneAsync(); int subscriptionId = 0; tabItemTabProc.TabItemClosed += async(o, e) => { _logger.LogMessage("tabitemclosed event"); await TaskScheduler.Default; DoUnsubscribe(); await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); _perfGraphToolWindowControl.TabControl.SelectedIndex = 0; // select main tab }; btnUpdateFilter.Click += async(o, e) => { await TaskScheduler.Default; DoUnsubscribe(); DoSubScribe(); }; btnUpdateFilter.RaiseEvent(new RoutedEventArgs(Button.ClickEvent)); void DoSubScribe() { var startcond = new EventMatch(this.EventFilter); subscriptionId = TelemetryNotificationService.Default.Subscribe(startcond, (telEvent) => { var output = new StringBuilder(telEvent.ToString()); switch (telEvent.Name) { case "vs/core/command": output.Append(":" + telEvent.Properties["vs.core.command.name"]); if (ShowAllProperties) { foreach (var item in telEvent.Properties) { output.AppendLine($" {item.Key} {item.Value}"); } } break; } if (UseOutputPane) { outputPane.OutputString(output.ToString() + Environment.NewLine); } else { _logger.LogMessage(output.ToString()); } }, singleNotification: false); _logger.LogMessage($"Subscribed to telemetry events. SubscriptionId={subscriptionId} EventFilter '{EventFilter}'"); } void DoUnsubscribe() { if (subscriptionId != 0) { TelemetryNotificationService.Default.Unsubscribe(subscriptionId); _logger.LogMessage($"Unsubscribe subscriptionId={subscriptionId} Filter='{EventFilter}'"); } } }
async Task DoInitializeAsync() { CloseableTabItem tabItemTabProc = GetTabItem(); var strxaml = $@"<Grid xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" xmlns:l=""clr-namespace:{this.GetType().Namespace};assembly={ System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().Location)}"" > <Grid.RowDefinitions> <RowDefinition Height=""auto""/> <RowDefinition Height=""*""/> </Grid.RowDefinitions> <StackPanel Grid.Row=""0"" HorizontalAlignment=""Left"" Height=""75"" VerticalAlignment=""Top"" Orientation=""Horizontal""> <CheckBox Margin=""15,0,0,10"" Content=""Output To Debug OutputPane"" IsChecked=""{{Binding UseOutputPane}}"" ToolTip=""Output to Debug OutputPane 'PerfGraphVSIX'""/> <TextBox xml:space=""preserve"" > IVsMonitorSelection until this tab is closed. Output to Debug OutputPane or LogStatus </TextBox> </StackPanel> <Grid Name=""gridUser"" Grid.Row = ""1""></Grid> </Grid> "; var strReader = new System.IO.StringReader(strxaml); var xamlreader = XmlReader.Create(strReader); var grid = (Grid)(XamlReader.Load(xamlreader)); tabItemTabProc.Content = grid; grid.DataContext = this; var gridUser = (Grid)grid.FindName("gridUser"); _OutputPane = await GetOutputPaneAsync(); _OutputPane.Clear(); uint cookieSelectionEvents = 0; uint cookieRdt = 0; await ThreadHelper.JoinableTaskFactory.RunAsync(async() => { LogMessage("Here in MySimpleSample " + DateTime.Now.ToString("MM/dd/yy hh:mm:ss")); await TaskScheduler.Default; // switch to background thread LogMessage("Logger message from MySimpleSample"); var SolutionService = await _asyncServiceProvider.GetServiceAsync(typeof(SVsSolution)) as IVsSolution; LogMessage($"{nameof(SolutionService)} {SolutionService}"); var oleMenuCommandService = await _asyncServiceProvider.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService; LogMessage($"{nameof(oleMenuCommandService)} = {oleMenuCommandService}"); var VsShellMonitorSelection = await _asyncServiceProvider.GetServiceAsync(typeof(SVsShellMonitorSelection)) as IVsMonitorSelection; LogMessage($"{nameof(VsShellMonitorSelection)} = {VsShellMonitorSelection}"); VsShellMonitorSelection.AdviseSelectionEvents(this, out cookieSelectionEvents); IVsRunningDocumentTable vsRunningDocumentTable = await _asyncServiceProvider.GetServiceAsync(typeof(IVsRunningDocumentTable)) as IVsRunningDocumentTable; //vsRunningDocumentTable.AdviseRunningDocTableEvents(this, out cookieRdt); void UnSubscribe() { VsShellMonitorSelection.UnadviseSelectionEvents(cookieSelectionEvents); vsRunningDocumentTable.UnadviseRunningDocTableEvents(cookieRdt); } tabItemTabProc.TabItemClosed += async(o, e) => { UnSubscribe(); await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); _perfGraphToolWindowControl.TabControl.SelectedIndex = 0; }; }); }
async Task InitializeAsync() { await Task.Yield(); CloseableTabItem tabItemTabProc = GetTabItem(); var strxaml = $@"<Grid xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" xmlns:l=""clr-namespace:{this.GetType().Namespace};assembly={ System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().Location)}"" > <Grid.RowDefinitions> <RowDefinition Height=""auto""/> <RowDefinition Height=""*""/> </Grid.RowDefinitions> <Canvas Margin=""311,0,0,0.5""> <!--An animated circle indicates UI delays easily --> <Ellipse Name=""Ball"" Width=""24"" Height=""24"" Fill=""Blue"" Canvas.Left=""396""> <Ellipse.Triggers> <EventTrigger RoutedEvent=""Ellipse.Loaded""> <BeginStoryboard> <Storyboard TargetName=""Ball"" RepeatBehavior=""Forever""> <DoubleAnimation Storyboard.TargetProperty=""(Canvas.Left)"" From=""96"" To=""300"" Duration=""0:0:1"" AutoReverse=""True"" /> </Storyboard> </BeginStoryboard> </EventTrigger> <!-- <EventTrigger RoutedEvent=""CheckBox.Checked"" SourceName=""ChkBoxMonitor""> <PauseStoryboard BeginStoryboardName=""MyBeginStoryboard"" /> </EventTrigger> <EventTrigger RoutedEvent=""CheckBox.Unchecked"" SourceName=""ChkBoxMonitor""> <ResumeStoryboard BeginStoryboardName=""MyBeginStoryboard"" /> </EventTrigger> --> </Ellipse.Triggers> </Ellipse> </Canvas> <StackPanel Grid.Row=""0"" HorizontalAlignment=""Left"" Height=""28"" VerticalAlignment=""Top"" Orientation=""Horizontal""> <Label Content=""Refresh Rate""/> <TextBox Text=""{{Binding RefreshRate}}"" Width=""40"" Height=""20"" ToolTip=""mSeconds. Refresh means check child process. UI won't update UI if tree is same. 0 means don't refresh"" /> <CheckBox Margin=""15,2,0,10"" Content=""EatMem"" IsChecked=""{{Binding EatMem}}"" Name=""chkBoxEatMem"" ToolTip=""Eat Mem""/> <TextBox Text=""{{Binding AmountToEat}}"" Width=""100"" Height=""20"" ToolTip=""AmountToEat in MBytes"" /> <!-- <CheckBox Margin=""15,0,0,10"" Content=""Monitor"" IsChecked=""{{Binding Monitor}}"" Name=""ChkBoxMonitor"" ToolTip=""Monitor Child Processes""/> <CheckBox Margin=""15,0,0,10"" Content=""Show Memory Changes too"" IsChecked=""{{Binding ShowMemChangestoo}}"" ToolTip=""Update the tree for memory changes. The bouncing ball will be jerky on UI updates""/> --> </StackPanel> <Grid Name=""gridUser"" Grid.Row = ""1""></Grid> </Grid> "; var strReader = new System.IO.StringReader(strxaml); var xamlreader = XmlReader.Create(strReader); var grid = (Grid)(XamlReader.Load(xamlreader)); tabItemTabProc.Content = grid; grid.DataContext = this; var gridUser = (Grid)grid.FindName("gridUser"); var chkEatMem = (CheckBox)grid.FindName("chkBoxEatMem"); var addrAllocated = IntPtr.Zero; void EatMemHandler(object sender, RoutedEventArgs e) { if (chkEatMem.IsChecked == true) { addrAllocated = VirtualAlloc(IntPtr.Zero, AmountToEat * 1024 * 1024, AllocationType.Commit, MemoryProtection.ReadWrite); _logger.LogMessage($"Alloc {AmountToEat:n0} {addrAllocated.ToInt32():x8}"); } else { var res = VirtualFree(addrAllocated, 0, FreeType.Release); _logger.LogMessage($"Freed {res}"); } } chkEatMem.Checked += EatMemHandler; chkEatMem.Unchecked += EatMemHandler; var ctsCancelMonitor = new CancellationTokenSource(); tabItemTabProc.TabItemClosed += (o, e) => { //_logger.LogMessage("close event"); if (addrAllocated != IntPtr.Zero) { VirtualFree(addrAllocated, 0, FreeType.Release); } ctsCancelMonitor.Cancel(); _perfGraphToolWindowControl.TabControl.SelectedIndex = 0; }; _ = ThreadHelper.JoinableTaskFactory.RunAsync(async() => { ChildProcTree childProcTree = new ChildProcTree(); try { gridUser.Children.Clear(); gridUser.Children.Add(childProcTree); int hashLastTree = 0; DateTime dtlastTree; while (!ctsCancelMonitor.IsCancellationRequested) { await TaskScheduler.Default; if (Monitor && RefreshRate > 0) { var processEx = new ProcessEx(); var devenvTree = processEx.GetProcessTree(Process.GetCurrentProcess().Id); var curHash = 0; processEx.IterateTreeNodes(devenvTree, level: 0, func: (node, level) => { curHash += node.ProcEntry.szExeFile.GetHashCode() + node.procId.GetHashCode(); return(true); }); if (curHash != hashLastTree) { // get the mem measurements on background thread processEx.IterateTreeNodes(devenvTree, level: 0, func: (node, level) => { _ = node.MemSize.Value; // instantiate lazy return(true); }); dtlastTree = DateTime.Now; await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); childProcTree.Items.Clear(); childProcTree.AddNodes(childProcTree, devenvTree); childProcTree.ToolTip = $"Refreshed {dtlastTree}"; await TaskScheduler.Default; if (!ShowMemChangestoo) { hashLastTree = curHash; } } } //_logger.LogMessage("in loop"); await Task.Delay(TimeSpan.FromMilliseconds(RefreshRate), ctsCancelMonitor.Token); } } catch (OperationCanceledException) { } catch (Exception ex) { _logger.LogMessage(ex.ToString()); } //_logger.LogMessage("Monitor done"); //await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); //childProcTree.Background = Brushes.Cornsilk; }); }