From 82f048d497464a33eb21f74a3642b81256d63f96 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Wed, 29 Jan 2020 14:00:45 +0100 Subject: [PATCH] Add "Select PDB..." context menu item on assemblies, to be able to manually load a PDB for an assembly. --- ILSpy/AssemblyList.cs | 10 +++- ILSpy/Commands/GeneratePdbContextMenuEntry.cs | 1 + ILSpy/Commands/SelectPdbContextMenuEntry.cs | 56 +++++++++++++++++++ ILSpy/ILSpy.csproj | 1 + ILSpy/LoadedAssembly.cs | 5 +- 5 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 ILSpy/Commands/SelectPdbContextMenuEntry.cs diff --git a/ILSpy/AssemblyList.cs b/ILSpy/AssemblyList.cs index 6739bf1c5e..612dc77d97 100644 --- a/ILSpy/AssemblyList.cs +++ b/ILSpy/AssemblyList.cs @@ -244,16 +244,22 @@ public LoadedAssembly ReloadAssembly(string file) if (target == null) return null; + return ReloadAssembly(target); + } + + public LoadedAssembly ReloadAssembly(LoadedAssembly target) + { var index = this.assemblies.IndexOf(target); - var newAsm = new LoadedAssembly(this, file); + var newAsm = new LoadedAssembly(this, target.FileName); newAsm.IsAutoLoaded = target.IsAutoLoaded; + newAsm.PdbFileOverride = target.PdbFileOverride; lock (assemblies) { this.assemblies.Remove(target); this.assemblies.Insert(index, newAsm); } return newAsm; } - + public void Unload(LoadedAssembly assembly) { App.Current.Dispatcher.VerifyAccess(); diff --git a/ILSpy/Commands/GeneratePdbContextMenuEntry.cs b/ILSpy/Commands/GeneratePdbContextMenuEntry.cs index de254cfd4d..9bea8740e9 100644 --- a/ILSpy/Commands/GeneratePdbContextMenuEntry.cs +++ b/ILSpy/Commands/GeneratePdbContextMenuEntry.cs @@ -29,6 +29,7 @@ using ICSharpCode.ILSpy.TreeNodes; using Microsoft.Win32; using ICSharpCode.ILSpy.Properties; + namespace ICSharpCode.ILSpy { [ExportContextMenuEntry(Header = "Generate portable PDB")] diff --git a/ILSpy/Commands/SelectPdbContextMenuEntry.cs b/ILSpy/Commands/SelectPdbContextMenuEntry.cs new file mode 100644 index 0000000000..3303ca15c0 --- /dev/null +++ b/ILSpy/Commands/SelectPdbContextMenuEntry.cs @@ -0,0 +1,56 @@ +// Copyright (c) 2018 Siegfried Pammer +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System.IO; +using System.Linq; +using ICSharpCode.ILSpy.TextView; +using ICSharpCode.ILSpy.TreeNodes; +using Microsoft.Win32; +namespace ICSharpCode.ILSpy +{ + [ExportContextMenuEntry(Header = "Select PDB...")] + class SelectPdbContextMenuEntry : IContextMenuEntry + { + public void Execute(TextViewContext context) + { + var assembly = (context.SelectedTreeNodes?.FirstOrDefault() as AssemblyTreeNode)?.LoadedAssembly; + if (assembly == null) return; + OpenFileDialog dlg = new OpenFileDialog(); + dlg.FileName = DecompilerTextView.CleanUpName(assembly.ShortName) + ".pdb"; + dlg.Filter = "Portable PDB|*.pdb|All files|*.*"; + dlg.InitialDirectory = Path.GetDirectoryName(assembly.FileName); + if (dlg.ShowDialog() != true) return; + + using (context.TreeView.LockUpdates()) { + assembly.PdbFileOverride = dlg.FileName; + assembly.AssemblyList.ReloadAssembly(assembly); + } + + MainWindow.Instance.SelectNode(MainWindow.Instance.FindNodeByPath(new[] { assembly.FileName }, true)); + MainWindow.Instance.RefreshDecompiledView(); + } + + public bool IsEnabled(TextViewContext context) => true; + + public bool IsVisible(TextViewContext context) + { + return context.SelectedTreeNodes?.Length == 1 + && context.SelectedTreeNodes?.FirstOrDefault() is AssemblyTreeNode; + } + } +} diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 93f16b6396..d16971766b 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -118,6 +118,7 @@ + diff --git a/ILSpy/LoadedAssembly.cs b/ILSpy/LoadedAssembly.cs index 427d1171ad..0e30511262 100644 --- a/ILSpy/LoadedAssembly.cs +++ b/ILSpy/LoadedAssembly.cs @@ -143,6 +143,8 @@ public string Text { public bool IsAutoLoaded { get; set; } + public string PdbFileOverride { get; set; } + PEFile LoadAssembly(object state) { MetadataReaderOptions options; @@ -167,7 +169,8 @@ PEFile LoadAssembly(object state) if (DecompilerSettingsPanel.CurrentDecompilerSettings.UseDebugSymbols) { try { - debugInfoProvider = DebugInfoUtils.LoadSymbols(module); + debugInfoProvider = DebugInfoUtils.FromFile(module, PdbFileOverride) + ?? DebugInfoUtils.LoadSymbols(module); } catch (IOException) { } catch (UnauthorizedAccessException) { } catch (InvalidOperationException) {