diff --git a/ILSpy.AddIn/Commands/OpenReferenceCommand.cs b/ILSpy.AddIn/Commands/OpenReferenceCommand.cs index 5c2b61fa8..dd6ab3581 100644 --- a/ILSpy.AddIn/Commands/OpenReferenceCommand.cs +++ b/ILSpy.AddIn/Commands/OpenReferenceCommand.cs @@ -59,12 +59,14 @@ namespace ICSharpCode.ILSpy.AddIn.Commands OpenAssembliesInILSpy(parameters); else owner.ShowMessage("Could not find reference '{0}', please ensure the project and all references were built correctly!", reference.Name); + return; } // Handle NuGet references var nugetRefItem = NuGetReferenceForILSpy.Detect(itemObject); if (nugetRefItem != null) { OpenAssembliesInILSpy(nugetRefItem.GetILSpyParameters()); + return; } // Handle project references diff --git a/ILSpy/MainWindow.xaml.cs b/ILSpy/MainWindow.xaml.cs index 5732b5673..4563dd602 100644 --- a/ILSpy/MainWindow.xaml.cs +++ b/ILSpy/MainWindow.xaml.cs @@ -53,26 +53,27 @@ namespace ICSharpCode.ILSpy partial class MainWindow : Window { bool refreshInProgress; + bool handlingNugetPackageSelection; readonly NavigationHistory history = new NavigationHistory(); ILSpySettings spySettingsForMainWindow_Loaded; internal SessionSettings sessionSettings; - + internal AssemblyListManager assemblyListManager; AssemblyList assemblyList; AssemblyListTreeNode assemblyListTreeNode; - + readonly DecompilerTextView decompilerTextView; - + static MainWindow instance; - + public static MainWindow Instance { get { return instance; } } - + public SessionSettings SessionSettings { get { return sessionSettings; } } - + public MainWindow() { instance = this; @@ -80,28 +81,28 @@ namespace ICSharpCode.ILSpy this.spySettingsForMainWindow_Loaded = spySettings; this.sessionSettings = new SessionSettings(spySettings); this.assemblyListManager = new AssemblyListManager(spySettings); - + this.Icon = new BitmapImage(new Uri("pack://application:,,,/ILSpy;component/images/ILSpy.ico")); - + this.DataContext = sessionSettings; - + InitializeComponent(); decompilerTextView = App.ExportProvider.GetExportedValue(); mainPane.Content = decompilerTextView; - + if (sessionSettings.SplitterPosition > 0 && sessionSettings.SplitterPosition < 1) { leftColumn.Width = new GridLength(sessionSettings.SplitterPosition, GridUnitType.Star); rightColumn.Width = new GridLength(1 - sessionSettings.SplitterPosition, GridUnitType.Star); } sessionSettings.FilterSettings.PropertyChanged += filterSettings_PropertyChanged; - + InitMainMenu(); InitToolbar(); ContextMenuProvider.Add(treeView, decompilerTextView); - + this.Loaded += MainWindow_Loaded; } - + void SetWindowBounds(Rect bounds) { this.Left = bounds.Left; @@ -109,9 +110,9 @@ namespace ICSharpCode.ILSpy this.Width = bounds.Width; this.Height = bounds.Height; } - + #region Toolbar extensibility - + void InitToolbar() { int navigationPos = 0; @@ -134,14 +135,14 @@ namespace ICSharpCode.ILSpy } } } - + } - + Button MakeToolbarItem(Lazy command) { return new Button { Command = CommandWrapper.Unwrap(command.Value), - ToolTip =Properties.Resources.ResourceManager.GetString( command.Metadata.ToolTip), + ToolTip = Properties.Resources.ResourceManager.GetString(command.Metadata.ToolTip), Tag = command.Metadata.Tag, Content = new Image { Width = 16, @@ -151,9 +152,9 @@ namespace ICSharpCode.ILSpy }; } #endregion - + #region Main Menu extensibility - + void InitMainMenu() { var mainMenuCommands = App.ExportProvider.GetExports("MainMenuCommand"); @@ -190,8 +191,8 @@ namespace ICSharpCode.ILSpy internal static string GetResourceString(string key) { - var str = !string.IsNullOrEmpty(key)? Properties.Resources.ResourceManager.GetString(key):null; - return string.IsNullOrEmpty(key)|| string.IsNullOrEmpty(str) ? key : str; + var str = !string.IsNullOrEmpty(key) ? Properties.Resources.ResourceManager.GetString(key) : null; + return string.IsNullOrEmpty(key) || string.IsNullOrEmpty(str) ? key : str; } #endregion @@ -217,16 +218,18 @@ namespace ICSharpCode.ILSpy SetWindowBounds(sessionSettings.WindowBounds); else SetWindowBounds(SessionSettings.DefaultWindowBounds); - + this.WindowState = sessionSettings.WindowState; } - + unsafe IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { if (msg == NativeMethods.WM_COPYDATA) { CopyDataStruct* copyData = (CopyDataStruct*)lParam; string data = new string((char*)copyData->Buffer, 0, copyData->Size / sizeof(char)); if (data.StartsWith("ILSpy:\r\n", StringComparison.Ordinal)) { + if (handlingNugetPackageSelection) + return (IntPtr)1; data = data.Substring(8); List lines = new List(); using (StringReader r = new StringReader(data)) { @@ -247,17 +250,17 @@ namespace ICSharpCode.ILSpy return IntPtr.Zero; } #endregion - + public AssemblyList CurrentAssemblyList { get { return assemblyList; } } - + public event NotifyCollectionChangedEventHandler CurrentAssemblyListChanged; - + List commandLineLoadedAssemblies = new List(); List nugetPackagesToLoad = new List(); - + bool HandleCommandLineArguments(CommandLineArguments args) { int i = 0; @@ -270,12 +273,12 @@ namespace ICSharpCode.ILSpy i++; } } - LoadAssemblies(args.AssembliesToLoad, commandLineLoadedAssemblies, false); + LoadAssemblies(args.AssembliesToLoad, commandLineLoadedAssemblies, focusNode: false); if (args.Language != null) sessionSettings.FilterSettings.Language = Languages.GetLanguage(args.Language); return true; } - + /// /// Called on startup or when passed arguments via WndProc from a second instance. /// In the format case, spySettings is non-null; in the latter it is null. @@ -283,14 +286,15 @@ namespace ICSharpCode.ILSpy void HandleCommandLineArgumentsAfterShowList(CommandLineArguments args, ILSpySettings spySettings = null) { if (nugetPackagesToLoad.Count > 0) { - LoadAssemblies(nugetPackagesToLoad, commandLineLoadedAssemblies, focusNode: false); + var relevantPackages = nugetPackagesToLoad.ToArray(); nugetPackagesToLoad.Clear(); + // Show the nuget package open dialog after the command line/window message was processed. + Dispatcher.BeginInvoke(new Action(() => LoadAssemblies(relevantPackages, commandLineLoadedAssemblies, focusNode: false)), DispatcherPriority.Normal); } var relevantAssemblies = commandLineLoadedAssemblies.ToList(); commandLineLoadedAssemblies.Clear(); // clear references once we don't need them anymore NavigateOnLaunch(args.NavigateTo, sessionSettings.ActiveTreeViewPath, spySettings, relevantAssemblies); - if (args.Search != null) - { + if (args.Search != null) { SearchPane.Instance.SearchTerm = args.Search; SearchPane.Instance.Show(); } @@ -448,12 +452,12 @@ namespace ICSharpCode.ILSpy void OpenAssemblies(ILSpySettings spySettings) { HandleCommandLineArgumentsAfterShowList(App.CommandLineArguments, spySettings); - + AvalonEditTextOutput output = new AvalonEditTextOutput(); if (FormatExceptions(App.StartupExceptions.ToArray(), output)) decompilerTextView.ShowText(output); } - + bool FormatExceptions(App.ExceptionData[] exceptions, ITextOutput output) { var stringBuilder = new StringBuilder(); @@ -468,7 +472,7 @@ namespace ICSharpCode.ILSpy { if (exceptions.Length == 0) return false; bool first = true; - + foreach (var item in exceptions) { if (first) first = false; @@ -484,17 +488,17 @@ namespace ICSharpCode.ILSpy } else output.AppendLine(item.Exception.ToString()); } - + return true; } - + #region Update Check string updateAvailableDownloadUrl; - + public void ShowMessageIfUpdatesAvailableAsync(ILSpySettings spySettings, bool forceCheck = false) { // Don't check for updates if we're in an MSIX since they work differently - if(WindowsVersionHelper.HasPackageIdentity) { + if (WindowsVersionHelper.HasPackageIdentity) { return; } @@ -506,12 +510,12 @@ namespace ICSharpCode.ILSpy } result.ContinueWith(task => AdjustUpdateUIAfterCheck(task, forceCheck), TaskScheduler.FromCurrentSynchronizationContext()); } - + void updatePanelCloseButtonClick(object sender, RoutedEventArgs e) { updatePanel.Visibility = Visibility.Collapsed; } - + void downloadOrCheckUpdateButtonClick(object sender, RoutedEventArgs e) { if (updateAvailableDownloadUrl != null) { @@ -536,30 +540,29 @@ namespace ICSharpCode.ILSpy } } #endregion - + public void ShowAssemblyList(string name) { ILSpySettings settings = ILSpySettings.Load(); AssemblyList list = this.assemblyListManager.LoadList(settings, name); //Only load a new list when it is a different one - if (list.ListName != CurrentAssemblyList.ListName) - { + if (list.ListName != CurrentAssemblyList.ListName) { ShowAssemblyList(list); } } - + void ShowAssemblyList(AssemblyList assemblyList) { history.Clear(); this.assemblyList = assemblyList; - + assemblyList.assemblies.CollectionChanged += assemblyList_Assemblies_CollectionChanged; - + assemblyListTreeNode = new AssemblyListTreeNode(assemblyList); assemblyListTreeNode.FilterSettings = sessionSettings.FilterSettings.Clone(); assemblyListTreeNode.Select = SelectNode; treeView.Root = assemblyListTreeNode; - + if (assemblyList.ListName == AssemblyListManager.DefaultListName) #if DEBUG this.Title = $"ILSpy {RevisionClass.FullVersion}"; @@ -588,7 +591,7 @@ namespace ICSharpCode.ILSpy if (CurrentAssemblyListChanged != null) CurrentAssemblyListChanged(this, e); } - + void LoadInitialAssemblies() { // Called when loading an empty assembly list; so that @@ -606,7 +609,7 @@ namespace ICSharpCode.ILSpy foreach (System.Reflection.Assembly asm in initialAssemblies) assemblyList.OpenAssembly(asm.Location); } - + void filterSettings_PropertyChanged(object sender, PropertyChangedEventArgs e) { RefreshTreeViewFilter(); @@ -614,7 +617,7 @@ namespace ICSharpCode.ILSpy DecompileSelectedNodes(recordHistory: false); } } - + public void RefreshTreeViewFilter() { // filterSettings is mutable; but the ILSpyTreeNode filtering assumes that filter settings are immutable. @@ -623,11 +626,11 @@ namespace ICSharpCode.ILSpy if (assemblyListTreeNode != null) assemblyListTreeNode.FilterSettings = sessionSettings.FilterSettings.Clone(); } - + internal AssemblyListTreeNode AssemblyListTreeNode { get { return assemblyListTreeNode; } } - + #region Node Selection public void SelectNode(SharpTreeNode obj) @@ -653,7 +656,7 @@ namespace ICSharpCode.ILSpy treeView.SetSelectedNodes(nodes); } } - + /// /// Retrieves a node using the .ToString() representations of its ancestors. /// @@ -678,7 +681,7 @@ namespace ICSharpCode.ILSpy else return node; } - + /// /// Gets the .ToString() representation of the node's ancestors. /// @@ -694,7 +697,7 @@ namespace ICSharpCode.ILSpy path.Reverse(); return path.ToArray(); } - + public ILSpyTreeNode FindTreeNode(object reference) { switch (reference) { @@ -716,12 +719,12 @@ namespace ICSharpCode.ILSpy return null; } } - + public void JumpToReference(object reference) { JumpToReferenceAsync(reference).HandleExceptions(); } - + /// /// Jumps to the specified reference. /// @@ -792,7 +795,7 @@ namespace ICSharpCode.ILSpy { if (fileNames == null) throw new ArgumentNullException(nameof(fileNames)); - + if (focusNode) treeView.UnselectAll(); @@ -805,24 +808,29 @@ namespace ICSharpCode.ILSpy foreach (string file in fileNames) { switch (Path.GetExtension(file)) { case ".nupkg": - LoadedNugetPackage package = new LoadedNugetPackage(file); - var selectionDialog = new NugetPackageBrowserDialog(package); - selectionDialog.Owner = this; - if (selectionDialog.ShowDialog() != true) - break; - foreach (var entry in selectionDialog.SelectedItems) { - var nugetAsm = assemblyList.OpenAssembly("nupkg://" + file + ";" + entry.Name, entry.Stream, true); - if (nugetAsm != null) { - if (loadedAssemblies != null) - loadedAssemblies.Add(nugetAsm); - else { - var node = assemblyListTreeNode.FindAssemblyNode(nugetAsm); - if (node != null && focusNode) { - treeView.SelectedItems.Add(node); - lastNode = node; + this.handlingNugetPackageSelection = true; + try { + LoadedNugetPackage package = new LoadedNugetPackage(file); + var selectionDialog = new NugetPackageBrowserDialog(package); + selectionDialog.Owner = this; + if (selectionDialog.ShowDialog() != true) + break; + foreach (var entry in selectionDialog.SelectedItems) { + var nugetAsm = assemblyList.OpenAssembly("nupkg://" + file + ";" + entry.Name, entry.Stream, true); + if (nugetAsm != null) { + if (loadedAssemblies != null) + loadedAssemblies.Add(nugetAsm); + else { + var node = assemblyListTreeNode.FindAssemblyNode(nugetAsm); + if (node != null && focusNode) { + treeView.SelectedItems.Add(node); + lastNode = node; + } } } } + } finally { + this.handlingNugetPackageSelection = false; } break; default: @@ -845,7 +853,7 @@ namespace ICSharpCode.ILSpy treeView.FocusNode(lastNode); } } - + void RefreshCommandExecuted(object sender, ExecutedRoutedEventArgs e) { try { @@ -857,13 +865,13 @@ namespace ICSharpCode.ILSpy refreshInProgress = false; } } - + void SearchCommandExecuted(object sender, ExecutedRoutedEventArgs e) { SearchPane.Instance.Show(); } #endregion - + #region Decompile (TreeView_SelectionChanged) void TreeView_SelectionChanged(object sender, SelectionChangedEventArgs e) { @@ -872,10 +880,10 @@ namespace ICSharpCode.ILSpy if (SelectionChanged != null) SelectionChanged(sender, e); } - + Task decompilationTask; bool ignoreDecompilationRequests; - + void DecompileSelectedNodes(DecompilerTextViewState state = null, bool recordHistory = true) { if (ignoreDecompilationRequests) @@ -883,14 +891,14 @@ namespace ICSharpCode.ILSpy if (treeView.SelectedItems.Count == 0 && refreshInProgress) return; - + if (recordHistory) { var dtState = decompilerTextView.GetState(); - if(dtState != null) + if (dtState != null) history.UpdateCurrent(new NavigationState(dtState)); history.Record(new NavigationState(treeView.SelectedItems.OfType())); } - + if (treeView.SelectedItems.Count == 1) { ILSpyTreeNode node = treeView.SelectedItem as ILSpyTreeNode; if (node != null && node.View(decompilerTextView)) @@ -919,7 +927,7 @@ namespace ICSharpCode.ILSpy refreshInProgress = false; } } - + public DecompilerTextView TextView { get { return decompilerTextView; } } @@ -942,7 +950,7 @@ namespace ICSharpCode.ILSpy e.Handled = true; e.CanExecute = history.CanNavigateBack; } - + void BackCommandExecuted(object sender, ExecutedRoutedEventArgs e) { if (history.CanNavigateBack) { @@ -950,13 +958,13 @@ namespace ICSharpCode.ILSpy NavigateHistory(false); } } - + void ForwardCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.Handled = true; e.CanExecute = history.CanNavigateForward; } - + void ForwardCommandExecuted(object sender, ExecutedRoutedEventArgs e) { if (history.CanNavigateForward) { @@ -964,18 +972,17 @@ namespace ICSharpCode.ILSpy NavigateHistory(true); } } - + void NavigateHistory(bool forward) { var dtState = decompilerTextView.GetState(); - if(dtState != null) + if (dtState != null) history.UpdateCurrent(new NavigationState(dtState)); var newState = forward ? history.GoForward() : history.GoBack(); - + ignoreDecompilationRequests = true; treeView.SelectedItems.Clear(); - foreach (var node in newState.TreeNodes) - { + foreach (var node in newState.TreeNodes) { treeView.SelectedItems.Add(node); } if (newState.TreeNodes.Any()) @@ -983,9 +990,9 @@ namespace ICSharpCode.ILSpy ignoreDecompilationRequests = false; DecompileSelectedNodes(newState.ViewState, false); } - + #endregion - + protected override void OnStateChanged(EventArgs e) { base.OnStateChanged(e); @@ -993,7 +1000,7 @@ namespace ICSharpCode.ILSpy if (this.WindowState != System.Windows.WindowState.Minimized) sessionSettings.WindowState = this.WindowState; } - + protected override void OnClosing(CancelEventArgs e) { base.OnClosing(e); @@ -1024,7 +1031,7 @@ namespace ICSharpCode.ILSpy return loadedAssy.FileName; } - + #region Top/Bottom Pane management /// @@ -1038,14 +1045,12 @@ namespace ICSharpCode.ILSpy var pane2Height = pane2Row.Height; //only star height values are normalized. - if (!pane1Height.IsStar || !pane2Height.IsStar) - { + if (!pane1Height.IsStar || !pane2Height.IsStar) { return; } var totalHeight = pane1Height.Value + pane2Height.Value; - if (totalHeight == 0) - { + if (totalHeight == 0) { return; } @@ -1072,20 +1077,20 @@ namespace ICSharpCode.ILSpy } topPane.Visibility = Visibility.Visible; } - + void TopPane_CloseButtonClicked(object sender, EventArgs e) { sessionSettings.TopPaneSplitterPosition = topPaneRow.Height.Value / (topPaneRow.Height.Value + textViewRow.Height.Value); topPaneRow.MinHeight = 0; topPaneRow.Height = new GridLength(0); topPane.Visibility = Visibility.Collapsed; - + IPane pane = topPane.Content as IPane; topPane.Content = null; if (pane != null) pane.Closed(); } - + public void ShowInBottomPane(string title, object content) { bottomPaneRow.MinHeight = 100; @@ -1105,26 +1110,26 @@ namespace ICSharpCode.ILSpy } bottomPane.Visibility = Visibility.Visible; } - + void BottomPane_CloseButtonClicked(object sender, EventArgs e) { sessionSettings.BottomPaneSplitterPosition = bottomPaneRow.Height.Value / (bottomPaneRow.Height.Value + textViewRow.Height.Value); bottomPaneRow.MinHeight = 0; bottomPaneRow.Height = new GridLength(0); bottomPane.Visibility = Visibility.Collapsed; - + IPane pane = bottomPane.Content as IPane; bottomPane.Content = null; if (pane != null) pane.Closed(); } #endregion - + public void UnselectAll() { treeView.UnselectAll(); } - + public void SetStatus(string status, Brush foreground) { if (this.statusBar.Visibility == Visibility.Collapsed) @@ -1132,12 +1137,12 @@ namespace ICSharpCode.ILSpy this.StatusLabel.Foreground = foreground; this.StatusLabel.Text = status; } - + public ItemCollection GetMainMenuItems() { return mainMenu.Items; } - + public ItemCollection GetToolBarItems() { return toolBar.Items;