From 8654d91045154e75fc03a288883ccd3115e1c448 Mon Sep 17 00:00:00 2001 From: QianMoXi <26250460+QianMoXi@users.noreply.github.com> Date: Wed, 31 Jan 2024 17:51:46 +0800 Subject: [PATCH 1/6] Add the Dotnet runtime to the list of assemblies --- .../Documents/Tabs/DefaultDocumentList.cs | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/dnSpy/dnSpy/Documents/Tabs/DefaultDocumentList.cs b/dnSpy/dnSpy/Documents/Tabs/DefaultDocumentList.cs index 61b78905e3..8466ddcde0 100644 --- a/dnSpy/dnSpy/Documents/Tabs/DefaultDocumentList.cs +++ b/dnSpy/dnSpy/Documents/Tabs/DefaultDocumentList.cs @@ -20,6 +20,7 @@ You should have received a copy of the GNU General Public License using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Threading; @@ -48,6 +49,60 @@ public DefaultDocumentList(string name, IEnumerable asmNames) { public void Add(DsDocumentInfo file) => files.Add(file); } + sealed class DotnetReferenceFileFinder { + readonly CancellationToken cancellationToken; + readonly List allLists; + + public DotnetReferenceFileFinder(CancellationToken cancellationToken) { + this.cancellationToken = cancellationToken; + allLists = new List(); + } + + public IEnumerable AllFiles => allLists.ToArray(); + + public void Find() { + cancellationToken.ThrowIfCancellationRequested(); + + if (!TryGetRuntimeFolder(out var runtimesFolder)) { + return; + } + + foreach (var appDir in Directory.EnumerateDirectories(runtimesFolder)) { + foreach (var versionDir in Directory.EnumerateDirectories(appDir)) { + var appName = $"{Path.GetFileName(appDir)} {Path.GetFileName(versionDir)}"; + allLists.Add(new DefaultDocumentList(appName, Directory.GetFiles(versionDir, "*.dll").Where(FilterFiles).Select(DsDocumentInfo.CreateDocument))); + } + } + } + + static bool FilterFiles(string file) { + + var fileName = Path.GetFileName(file); + + //Here, only DLLs that are obviously not .NET assemblies are filtered out; other files are not filtered, and should not be affected, so to speak. + if (fileName.StartsWith("api-ms-win")) { + return false; + } + + return true; + } + + static bool TryGetRuntimeFolder([NotNullWhen(true)] out string path) { + path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"dotnet\shared"); + if (Directory.Exists(path)) { + return true; + } + + //The previous dotnet installation was in the x86 folder + path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), @"dotnet\shared"); + if (Directory.Exists(path)) { + return true; + } + + return false; + } + } + sealed class ReferenceFileFinder { readonly CancellationToken cancellationToken; readonly List allFiles; @@ -356,6 +411,9 @@ public DefaultDocumentList[] Find() { var finder = new ReferenceFileFinder(cancellationToken); finder.Find(); + var dotnetFinder = new DotnetReferenceFileFinder(cancellationToken); + dotnetFinder.Find(); + var xmlFiles = new List<(DefaultDocumentList list, bool isDefault)>(); foreach (var dir in FilesDirs) { cancellationToken.ThrowIfCancellationRequested(); @@ -381,6 +439,9 @@ public DefaultDocumentList[] Find() { foreach (var f in finder.AllFiles) dict[f.Name] = f; + foreach (var f in dotnetFinder.AllFiles) + dict[f.Name] = f; + foreach (var t in xmlFiles) { if (!t.isDefault) // if user file dict[t.list.Name] = t.list; From 0397526b1786bff894971d348c81a154df7781dd Mon Sep 17 00:00:00 2001 From: QianMoXi <26250460+QianMoXi@users.noreply.github.com> Date: Tue, 20 Feb 2024 11:34:32 +0800 Subject: [PATCH 2/6] use DotNetPathProvider to find paths --- .../Utilities/DotNetPathProvider.cs | 6 +++ .../Utilities/FrameworkPath.cs | 53 ++++++++++++++++++- .../Documents/Tabs/DefaultDocumentList.cs | 42 +++++++++++---- 3 files changed, 89 insertions(+), 12 deletions(-) diff --git a/dnSpy/dnSpy.Contracts.Logic/Utilities/DotNetPathProvider.cs b/dnSpy/dnSpy.Contracts.Logic/Utilities/DotNetPathProvider.cs index 661d482829..ac04e53b04 100644 --- a/dnSpy/dnSpy.Contracts.Logic/Utilities/DotNetPathProvider.cs +++ b/dnSpy/dnSpy.Contracts.Logic/Utilities/DotNetPathProvider.cs @@ -98,6 +98,12 @@ static FrameworkPaths[] CreateAndSortFrameworkPaths(IEnumerable l return array; } + /// + /// Returns the .NET Core runtime assembly directories found on the system. + /// + /// .NET Core framework path info + public FrameworkPath[] GetSharedDotNetPaths() => netPathsShared.SelectMany(x => x.frameworkPaths).ToArray(); + /// /// Returns the .NET Core runtime assembly directories found on the system. /// diff --git a/dnSpy/dnSpy.Contracts.Logic/Utilities/FrameworkPath.cs b/dnSpy/dnSpy.Contracts.Logic/Utilities/FrameworkPath.cs index 4fc5e3e122..4333df7fbe 100644 --- a/dnSpy/dnSpy.Contracts.Logic/Utilities/FrameworkPath.cs +++ b/dnSpy/dnSpy.Contracts.Logic/Utilities/FrameworkPath.cs @@ -31,10 +31,12 @@ sealed class FrameworkPaths : IComparable { public readonly FrameworkVersion Version; public readonly Version SystemVersion; public readonly bool IsReferencePath; + internal readonly FrameworkPath[] frameworkPaths; string DebuggerPaths => string.Join(Path.PathSeparator.ToString(), Paths); public FrameworkPaths(FrameworkPath[] paths, bool isRef) { + frameworkPaths = paths; var firstPath = paths[0]; #if DEBUG for (int i = 1; i < paths.Length; i++) { @@ -122,13 +124,32 @@ public bool IsCompatibleWithNetStandard(Version netStandardVersion) { } } + /// + /// .NET Core path info + /// // It's a class since very few of these are created [DebuggerDisplay("{Bitness,d}-bit {Version,nq} {Path,nq}")] - sealed class FrameworkPath { + public sealed class FrameworkPath { + /// + /// .NET Core assembly directories + /// public readonly string Path; + /// + /// assembly bitness + /// public readonly int Bitness; + /// + /// assembly version + /// public readonly FrameworkVersion Version; + /// + /// + /// + /// .NET Core assembly directories + /// assembly bitness + /// assembly version + /// is null public FrameworkPath(string path, int bitness, FrameworkVersion version) { Path = path ?? throw new ArgumentNullException(nameof(path)); Bitness = bitness; @@ -136,12 +157,34 @@ public FrameworkPath(string path, int bitness, FrameworkVersion version) { } } - readonly struct FrameworkVersion : IComparable, IEquatable { + /// + /// .NET Core version info + /// + public readonly struct FrameworkVersion : IComparable, IEquatable { + /// + /// the major component + /// public readonly int Major; + /// + /// the minor component + /// public readonly int Minor; + /// + /// the patch component + /// public readonly int Patch; + /// + /// the extra component + /// public readonly string Extra; + /// + /// + /// + /// the major component + /// the minor component + /// the patch component + /// the extra component public FrameworkVersion(int major, int minor, int patch, string extra) { Major = major; Minor = minor; @@ -149,12 +192,14 @@ public FrameworkVersion(int major, int minor, int patch, string extra) { Extra = extra; } + /// public override string ToString() { if (Extra.Length == 0) return $"{Major}.{Minor}.{Patch}"; return $"{Major}.{Minor}.{Patch}-{Extra}"; } + /// public int CompareTo(FrameworkVersion other) { int c = Major.CompareTo(other.Major); if (c != 0) @@ -178,13 +223,17 @@ static int CompareExtra(string a, string b) { return StringComparer.Ordinal.Compare(a, b); } + /// public bool Equals(FrameworkVersion other) => Major == other.Major && Minor == other.Minor && Patch == other.Patch && StringComparer.Ordinal.Equals(Extra, other.Extra); + /// public override bool Equals(object? obj) => obj is FrameworkVersion other && Equals(other); + + /// public override int GetHashCode() => Major ^ Minor ^ Patch ^ StringComparer.Ordinal.GetHashCode(Extra ?? string.Empty); } } diff --git a/dnSpy/dnSpy/Documents/Tabs/DefaultDocumentList.cs b/dnSpy/dnSpy/Documents/Tabs/DefaultDocumentList.cs index 8466ddcde0..d6c2ae5b95 100644 --- a/dnSpy/dnSpy/Documents/Tabs/DefaultDocumentList.cs +++ b/dnSpy/dnSpy/Documents/Tabs/DefaultDocumentList.cs @@ -27,6 +27,7 @@ You should have received a copy of the GNU General Public License using System.Xml.Linq; using dnSpy.Contracts.App; using dnSpy.Contracts.Documents; +using dnSpy.Contracts.Utilities; namespace dnSpy.Documents.Tabs { sealed class DefaultDocumentList { @@ -63,15 +64,12 @@ public DotnetReferenceFileFinder(CancellationToken cancellationToken) { public void Find() { cancellationToken.ThrowIfCancellationRequested(); - if (!TryGetRuntimeFolder(out var runtimesFolder)) { - return; - } + var dotNetPathProvider = new DotNetPathProvider(); - foreach (var appDir in Directory.EnumerateDirectories(runtimesFolder)) { - foreach (var versionDir in Directory.EnumerateDirectories(appDir)) { - var appName = $"{Path.GetFileName(appDir)} {Path.GetFileName(versionDir)}"; - allLists.Add(new DefaultDocumentList(appName, Directory.GetFiles(versionDir, "*.dll").Where(FilterFiles).Select(DsDocumentInfo.CreateDocument))); - } + foreach (var frameworkPath in dotNetPathProvider.GetSharedDotNetPaths()) { + cancellationToken.ThrowIfCancellationRequested(); + var appName = $"{Path.GetFileName(Path.GetDirectoryName(frameworkPath.Path))} {frameworkPath.Version} (x{frameworkPath.Bitness:d})"; + allLists.Add(new DefaultDocumentList(appName, Directory.GetFiles(frameworkPath.Path, "*.dll").Where(FilterFiles).Select(DsDocumentInfo.CreateDocument))); } } @@ -79,8 +77,32 @@ static bool FilterFiles(string file) { var fileName = Path.GetFileName(file); - //Here, only DLLs that are obviously not .NET assemblies are filtered out; other files are not filtered, and should not be affected, so to speak. - if (fileName.StartsWith("api-ms-win")) { + if (fileName.Length == 0) { + return false; + } + + //The official managed assemblies in .NET Core almost always start with uppercase characters, which makes it easy for quick filtering. + if (fileName[0] >= 'A' && fileName[0] <= 'Z') { + //Exclude native assemblies here + //Microsoft.NETCore.App + if (fileName.StartsWith("Microsoft.DiaSymReader.Native.")) { + return false; + } + + //Microsoft.WindowsDesktop.App + if (fileName.StartsWith("D3DCompiler_") || fileName.Equals("PenImc_cor3") || fileName.Equals("PresentationNative_cor3")) { + return false; + } + + return true; + } + else if(fileName[0] >= 'a' && fileName[0] <= 'z') { + //Include managed assemblies here + //Microsoft.NETCore.App + if (fileName.Equals("mscorlib") || fileName.Equals("netstandard")) { + return true; + } + return false; } From 27e3dd6ac82b7e8446e11733b23358706dc5e252 Mon Sep 17 00:00:00 2001 From: QianMoXi <26250460+QianMoXi@users.noreply.github.com> Date: Wed, 28 Feb 2024 09:45:14 +0800 Subject: [PATCH 3/6] Fix comments and remove unused methods --- .../Utilities/FrameworkPath.cs | 16 +++++----- .../Documents/Tabs/DefaultDocumentList.cs | 32 ++++--------------- 2 files changed, 15 insertions(+), 33 deletions(-) diff --git a/dnSpy/dnSpy.Contracts.Logic/Utilities/FrameworkPath.cs b/dnSpy/dnSpy.Contracts.Logic/Utilities/FrameworkPath.cs index 4333df7fbe..c9d7786681 100644 --- a/dnSpy/dnSpy.Contracts.Logic/Utilities/FrameworkPath.cs +++ b/dnSpy/dnSpy.Contracts.Logic/Utilities/FrameworkPath.cs @@ -135,16 +135,16 @@ public sealed class FrameworkPath { /// public readonly string Path; /// - /// assembly bitness + /// Assembly bitness /// public readonly int Bitness; /// - /// assembly version + /// Assembly version /// public readonly FrameworkVersion Version; /// - /// + /// Constructor /// /// .NET Core assembly directories /// assembly bitness @@ -162,24 +162,24 @@ public FrameworkPath(string path, int bitness, FrameworkVersion version) { /// public readonly struct FrameworkVersion : IComparable, IEquatable { /// - /// the major component + /// The major component /// public readonly int Major; /// - /// the minor component + /// The minor component /// public readonly int Minor; /// - /// the patch component + /// The patch component /// public readonly int Patch; /// - /// the extra component + /// The extra component /// public readonly string Extra; /// - /// + /// Constructor /// /// the major component /// the minor component diff --git a/dnSpy/dnSpy/Documents/Tabs/DefaultDocumentList.cs b/dnSpy/dnSpy/Documents/Tabs/DefaultDocumentList.cs index d6c2ae5b95..37ae2890ba 100644 --- a/dnSpy/dnSpy/Documents/Tabs/DefaultDocumentList.cs +++ b/dnSpy/dnSpy/Documents/Tabs/DefaultDocumentList.cs @@ -20,7 +20,6 @@ You should have received a copy of the GNU General Public License using System; using System.Collections.Generic; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Threading; @@ -74,22 +73,20 @@ public void Find() { } static bool FilterFiles(string file) { - var fileName = Path.GetFileName(file); - if (fileName.Length == 0) { + if (fileName.Length == 0) return false; - } - //The official managed assemblies in .NET Core almost always start with uppercase characters, which makes it easy for quick filtering. + // The official managed assemblies in .NET Core almost always start with uppercase characters, which makes it easy for quick filtering. if (fileName[0] >= 'A' && fileName[0] <= 'Z') { - //Exclude native assemblies here - //Microsoft.NETCore.App + // Exclude native assemblies here + // Microsoft.NETCore.App if (fileName.StartsWith("Microsoft.DiaSymReader.Native.")) { return false; } - //Microsoft.WindowsDesktop.App + // Microsoft.WindowsDesktop.App if (fileName.StartsWith("D3DCompiler_") || fileName.Equals("PenImc_cor3") || fileName.Equals("PresentationNative_cor3")) { return false; } @@ -97,8 +94,8 @@ static bool FilterFiles(string file) { return true; } else if(fileName[0] >= 'a' && fileName[0] <= 'z') { - //Include managed assemblies here - //Microsoft.NETCore.App + // Include managed assemblies here + // Microsoft.NETCore.App if (fileName.Equals("mscorlib") || fileName.Equals("netstandard")) { return true; } @@ -108,21 +105,6 @@ static bool FilterFiles(string file) { return true; } - - static bool TryGetRuntimeFolder([NotNullWhen(true)] out string path) { - path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"dotnet\shared"); - if (Directory.Exists(path)) { - return true; - } - - //The previous dotnet installation was in the x86 folder - path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), @"dotnet\shared"); - if (Directory.Exists(path)) { - return true; - } - - return false; - } } sealed class ReferenceFileFinder { From 79aef114b6456341ed4ec14a9b0fecf1092a8d73 Mon Sep 17 00:00:00 2001 From: QianMoXi <26250460+QianMoXi@users.noreply.github.com> Date: Wed, 28 Feb 2024 09:48:47 +0800 Subject: [PATCH 4/6] Fix comments --- .../dnSpy.Contracts.Logic/Utilities/FrameworkPath.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dnSpy/dnSpy.Contracts.Logic/Utilities/FrameworkPath.cs b/dnSpy/dnSpy.Contracts.Logic/Utilities/FrameworkPath.cs index c9d7786681..a40729d1a9 100644 --- a/dnSpy/dnSpy.Contracts.Logic/Utilities/FrameworkPath.cs +++ b/dnSpy/dnSpy.Contracts.Logic/Utilities/FrameworkPath.cs @@ -147,8 +147,8 @@ public sealed class FrameworkPath { /// Constructor /// /// .NET Core assembly directories - /// assembly bitness - /// assembly version + /// Assembly bitness + /// Assembly version /// is null public FrameworkPath(string path, int bitness, FrameworkVersion version) { Path = path ?? throw new ArgumentNullException(nameof(path)); @@ -181,10 +181,10 @@ public FrameworkPath(string path, int bitness, FrameworkVersion version) { /// /// Constructor /// - /// the major component - /// the minor component - /// the patch component - /// the extra component + /// The major component + /// The minor component + /// The patch component + /// The extra component public FrameworkVersion(int major, int minor, int patch, string extra) { Major = major; Minor = minor; From 4c0325df92ba0e9c98b18a4f3baeee0533872810 Mon Sep 17 00:00:00 2001 From: QianMoXi <26250460+QianMoXi@users.noreply.github.com> Date: Wed, 28 Feb 2024 09:50:43 +0800 Subject: [PATCH 5/6] Fix comments --- dnSpy/dnSpy.Contracts.Logic/Utilities/FrameworkPath.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dnSpy/dnSpy.Contracts.Logic/Utilities/FrameworkPath.cs b/dnSpy/dnSpy.Contracts.Logic/Utilities/FrameworkPath.cs index a40729d1a9..2579b24aa9 100644 --- a/dnSpy/dnSpy.Contracts.Logic/Utilities/FrameworkPath.cs +++ b/dnSpy/dnSpy.Contracts.Logic/Utilities/FrameworkPath.cs @@ -192,14 +192,14 @@ public FrameworkVersion(int major, int minor, int patch, string extra) { Extra = extra; } - /// + /// public override string ToString() { if (Extra.Length == 0) return $"{Major}.{Minor}.{Patch}"; return $"{Major}.{Minor}.{Patch}-{Extra}"; } - /// + /// public int CompareTo(FrameworkVersion other) { int c = Major.CompareTo(other.Major); if (c != 0) @@ -223,17 +223,17 @@ static int CompareExtra(string a, string b) { return StringComparer.Ordinal.Compare(a, b); } - /// + /// public bool Equals(FrameworkVersion other) => Major == other.Major && Minor == other.Minor && Patch == other.Patch && StringComparer.Ordinal.Equals(Extra, other.Extra); - /// + /// public override bool Equals(object? obj) => obj is FrameworkVersion other && Equals(other); - /// + /// public override int GetHashCode() => Major ^ Minor ^ Patch ^ StringComparer.Ordinal.GetHashCode(Extra ?? string.Empty); } } From dcd6c0474f6c1aef90f5cf8d55d18c18e1635365 Mon Sep 17 00:00:00 2001 From: ElektroKill Date: Fri, 1 Mar 2024 20:28:26 +0100 Subject: [PATCH 6/6] Minor fixups --- dnSpy/dnSpy/Documents/Tabs/DefaultDocumentList.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/dnSpy/dnSpy/Documents/Tabs/DefaultDocumentList.cs b/dnSpy/dnSpy/Documents/Tabs/DefaultDocumentList.cs index 37ae2890ba..6a6d2d3b75 100644 --- a/dnSpy/dnSpy/Documents/Tabs/DefaultDocumentList.cs +++ b/dnSpy/dnSpy/Documents/Tabs/DefaultDocumentList.cs @@ -82,23 +82,20 @@ static bool FilterFiles(string file) { if (fileName[0] >= 'A' && fileName[0] <= 'Z') { // Exclude native assemblies here // Microsoft.NETCore.App - if (fileName.StartsWith("Microsoft.DiaSymReader.Native.")) { + if (fileName.StartsWith("Microsoft.DiaSymReader.Native.", StringComparison.Ordinal)) return false; - } // Microsoft.WindowsDesktop.App - if (fileName.StartsWith("D3DCompiler_") || fileName.Equals("PenImc_cor3") || fileName.Equals("PresentationNative_cor3")) { + if (fileName.StartsWith("D3DCompiler_", StringComparison.Ordinal) || fileName.Equals("PenImc_cor3") || fileName.Equals("PresentationNative_cor3")) return false; - } return true; } - else if(fileName[0] >= 'a' && fileName[0] <= 'z') { + if (fileName[0] >= 'a' && fileName[0] <= 'z') { // Include managed assemblies here // Microsoft.NETCore.App - if (fileName.Equals("mscorlib") || fileName.Equals("netstandard")) { + if (fileName.Equals("mscorlib") || fileName.Equals("netstandard")) return true; - } return false; }