diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
index e1d135139..6a6ecb687 100644
--- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
+++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
@@ -430,7 +430,7 @@ namespace ICSharpCode.Decompiler.CSharp
settings.LoadInMemory = true;
var file = LoadPEFile(fileName, settings);
var resolver = new UniversalAssemblyResolver(fileName, settings.ThrowOnAssemblyResolveErrors,
- file.DetectTargetFrameworkId(),
+ file.DetectTargetFrameworkId(), file.DetectRuntimePack(),
settings.LoadInMemory ? PEStreamOptions.PrefetchMetadata : PEStreamOptions.Default,
settings.ApplyWindowsRuntimeProjections ? MetadataReaderOptions.ApplyWindowsRuntimeProjections : MetadataReaderOptions.None);
return new DecompilerTypeSystem(file, resolver);
diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
index 0e7fcdcac..80c9977ca 100644
--- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
+++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
@@ -91,6 +91,7 @@
+
diff --git a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs
index e2038e16b..82f154364 100644
--- a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs
+++ b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs
@@ -75,10 +75,13 @@ namespace ICSharpCode.Decompiler.Metadata
readonly List packageBasePaths = new List();
readonly Version targetFrameworkVersion;
readonly string dotnetBasePath = FindDotNetExeDirectory();
+ readonly string preferredRuntimePack;
- public DotNetCorePathFinder(TargetFrameworkIdentifier targetFramework, Version targetFrameworkVersion)
+ public DotNetCorePathFinder(TargetFrameworkIdentifier targetFramework, Version targetFrameworkVersion,
+ string preferredRuntimePack)
{
this.targetFrameworkVersion = targetFrameworkVersion;
+ this.preferredRuntimePack = preferredRuntimePack;
if (targetFramework == TargetFrameworkIdentifier.NETStandard)
{
@@ -90,8 +93,9 @@ namespace ICSharpCode.Decompiler.Metadata
}
}
- public DotNetCorePathFinder(string parentAssemblyFileName, string targetFrameworkIdString, TargetFrameworkIdentifier targetFramework, Version targetFrameworkVersion, ReferenceLoadInfo loadInfo = null)
- : this(targetFramework, targetFrameworkVersion)
+ public DotNetCorePathFinder(string parentAssemblyFileName, string targetFrameworkIdString, string preferredRuntimePack,
+ TargetFrameworkIdentifier targetFramework, Version targetFrameworkVersion, ReferenceLoadInfo loadInfo = null)
+ : this(targetFramework, targetFrameworkVersion, preferredRuntimePack)
{
string assemblyName = Path.GetFileNameWithoutExtension(parentAssemblyFileName);
string basePath = Path.GetDirectoryName(parentAssemblyFileName);
@@ -203,7 +207,15 @@ namespace ICSharpCode.Decompiler.Metadata
runtimePack = null;
return null;
}
- foreach (string pack in RuntimePacks)
+
+ IEnumerable runtimePacks = RuntimePacks;
+
+ if (preferredRuntimePack != null)
+ {
+ runtimePacks = new[] { preferredRuntimePack }.Concat(runtimePacks);
+ }
+
+ foreach (string pack in runtimePacks)
{
runtimePack = pack;
string basePath = Path.Combine(dotnetBasePath, "shared", pack);
diff --git a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs
index c9bf3d969..03387f61e 100644
--- a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs
+++ b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs
@@ -17,8 +17,6 @@
// DEALINGS IN THE SOFTWARE.
using System;
-using System.Collections.Generic;
-using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Text.RegularExpressions;
@@ -187,68 +185,42 @@ namespace ICSharpCode.Decompiler.Metadata
var refPathMatch = Regex.Match(assemblyPath, RefPathPattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);
return refPathMatch.Success;
}
- }
-
- public class ReferenceLoadInfo
- {
- readonly Dictionary loadedAssemblyReferences = new Dictionary();
- public void AddMessage(string fullName, MessageKind kind, string message)
+ public static string DetectRuntimePack(this PEFile assembly)
{
- lock (loadedAssemblyReferences)
+ if (assembly is null)
{
- if (!loadedAssemblyReferences.TryGetValue(fullName, out var referenceInfo))
- {
- referenceInfo = new UnresolvedAssemblyNameReference(fullName);
- loadedAssemblyReferences.Add(fullName, referenceInfo);
- }
- referenceInfo.Messages.Add((kind, message));
+ throw new ArgumentNullException(nameof(assembly));
}
- }
- public void AddMessageOnce(string fullName, MessageKind kind, string message)
- {
- lock (loadedAssemblyReferences)
+ var metadata = assembly.Metadata;
+
+ foreach (var r in metadata.AssemblyReferences)
{
- if (!loadedAssemblyReferences.TryGetValue(fullName, out var referenceInfo))
- {
- referenceInfo = new UnresolvedAssemblyNameReference(fullName);
- loadedAssemblyReferences.Add(fullName, referenceInfo);
- referenceInfo.Messages.Add((kind, message));
- }
- else
+ var reference = metadata.GetAssemblyReference(r);
+
+ if (reference.PublicKeyOrToken.IsNil)
+ continue;
+
+ if (metadata.StringComparer.Equals(reference.Name, "WindowsBase"))
{
- var lastMsg = referenceInfo.Messages.LastOrDefault();
- if (kind != lastMsg.Item1 && message != lastMsg.Item2)
- referenceInfo.Messages.Add((kind, message));
+ return "Microsoft.WindowsDesktop.App";
}
- }
- }
-
- public bool TryGetInfo(string fullName, out UnresolvedAssemblyNameReference info)
- {
- lock (loadedAssemblyReferences)
- {
- return loadedAssemblyReferences.TryGetValue(fullName, out info);
- }
- }
- public IReadOnlyList Entries {
- get {
- lock (loadedAssemblyReferences)
+ if (metadata.StringComparer.Equals(reference.Name, "PresentationFramework"))
{
- return loadedAssemblyReferences.Values.ToList();
+ return "Microsoft.WindowsDesktop.App";
}
- }
- }
- public bool HasErrors {
- get {
- lock (loadedAssemblyReferences)
+ if (metadata.StringComparer.Equals(reference.Name, "PresentationCore"))
{
- return loadedAssemblyReferences.Any(i => i.Value.HasErrors);
+ return "Microsoft.WindowsDesktop.App";
}
+
+ // TODO add support for ASP.NET Core
}
+
+ return "Microsoft.NETCore.App";
}
}
}
diff --git a/ICSharpCode.Decompiler/Metadata/ReferenceLoadInfo.cs b/ICSharpCode.Decompiler/Metadata/ReferenceLoadInfo.cs
new file mode 100644
index 000000000..53ef9ea6f
--- /dev/null
+++ b/ICSharpCode.Decompiler/Metadata/ReferenceLoadInfo.cs
@@ -0,0 +1,87 @@
+// 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;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace ICSharpCode.Decompiler.Metadata
+{
+ public class ReferenceLoadInfo
+ {
+ readonly Dictionary loadedAssemblyReferences = new Dictionary();
+
+ public void AddMessage(string fullName, MessageKind kind, string message)
+ {
+ lock (loadedAssemblyReferences)
+ {
+ if (!loadedAssemblyReferences.TryGetValue(fullName, out var referenceInfo))
+ {
+ referenceInfo = new UnresolvedAssemblyNameReference(fullName);
+ loadedAssemblyReferences.Add(fullName, referenceInfo);
+ }
+ referenceInfo.Messages.Add((kind, message));
+ }
+ }
+
+ public void AddMessageOnce(string fullName, MessageKind kind, string message)
+ {
+ lock (loadedAssemblyReferences)
+ {
+ if (!loadedAssemblyReferences.TryGetValue(fullName, out var referenceInfo))
+ {
+ referenceInfo = new UnresolvedAssemblyNameReference(fullName);
+ loadedAssemblyReferences.Add(fullName, referenceInfo);
+ referenceInfo.Messages.Add((kind, message));
+ }
+ else
+ {
+ var lastMsg = referenceInfo.Messages.LastOrDefault();
+ if (kind != lastMsg.Item1 && message != lastMsg.Item2)
+ referenceInfo.Messages.Add((kind, message));
+ }
+ }
+ }
+
+ public bool TryGetInfo(string fullName, out UnresolvedAssemblyNameReference info)
+ {
+ lock (loadedAssemblyReferences)
+ {
+ return loadedAssemblyReferences.TryGetValue(fullName, out info);
+ }
+ }
+
+ public IReadOnlyList Entries {
+ get {
+ lock (loadedAssemblyReferences)
+ {
+ return loadedAssemblyReferences.Values.ToList();
+ }
+ }
+ }
+
+ public bool HasErrors {
+ get {
+ lock (loadedAssemblyReferences)
+ {
+ return loadedAssemblyReferences.Any(i => i.Value.HasErrors);
+ }
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs
index 38e65bb03..49d803e12 100644
--- a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs
+++ b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs
@@ -88,6 +88,7 @@ namespace ICSharpCode.Decompiler.Metadata
}
readonly string targetFramework;
+ readonly string runtimePack;
readonly TargetFrameworkIdentifier targetFrameworkIdentifier;
readonly Version targetFrameworkVersion;
@@ -109,16 +110,20 @@ namespace ICSharpCode.Decompiler.Metadata
/// "Silverlight", if the string doesn't match any of these, the resolver falls back to ".NET Framework",
/// which is "classic" .NET <= 4.8.
///
+ ///
+ /// Identifier of the runtime pack this assembly was compiled for.
+ /// If omitted, falling back to "Microsoft.NETCore.App" and this is ignored in case of classic .NET
/// Options used for the .
/// Options used for the .
public UniversalAssemblyResolver(string mainAssemblyFileName, bool throwOnError, string targetFramework,
- PEStreamOptions streamOptions = PEStreamOptions.Default, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default)
+ string runtimePack = null, PEStreamOptions streamOptions = PEStreamOptions.Default, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default)
{
this.mainAssemblyFileName = mainAssemblyFileName;
this.throwOnError = throwOnError;
this.streamOptions = streamOptions;
this.metadataOptions = metadataOptions;
this.targetFramework = targetFramework ?? string.Empty;
+ this.runtimePack = runtimePack ?? "Microsoft.NETCore.App";
(targetFrameworkIdentifier, targetFrameworkVersion) = ParseTargetFramework(this.targetFramework);
if (mainAssemblyFileName != null)
@@ -228,7 +233,7 @@ namespace ICSharpCode.Decompiler.Metadata
return FindWindowsMetadataFile(name);
}
- string file = null;
+ string file;
switch (targetFrameworkIdentifier)
{
case TargetFrameworkIdentifier.NETCoreApp:
@@ -238,9 +243,9 @@ namespace ICSharpCode.Decompiler.Metadata
if (dotNetCorePathFinder == null)
{
if (mainAssemblyFileName == null)
- dotNetCorePathFinder = new DotNetCorePathFinder(targetFrameworkIdentifier, targetFrameworkVersion);
+ dotNetCorePathFinder = new DotNetCorePathFinder(targetFrameworkIdentifier, targetFrameworkVersion, runtimePack);
else
- dotNetCorePathFinder = new DotNetCorePathFinder(mainAssemblyFileName, targetFramework, targetFrameworkIdentifier, targetFrameworkVersion);
+ dotNetCorePathFinder = new DotNetCorePathFinder(mainAssemblyFileName, targetFramework, runtimePack, targetFrameworkIdentifier, targetFrameworkVersion);
foreach (var directory in directories)
{
dotNetCorePathFinder.AddSearchDirectory(directory);
diff --git a/ILSpy/LoadedAssembly.cs b/ILSpy/LoadedAssembly.cs
index 50060e3b2..0276fd9ae 100644
--- a/ILSpy/LoadedAssembly.cs
+++ b/ILSpy/LoadedAssembly.cs
@@ -116,6 +116,12 @@ namespace ICSharpCode.ILSpy
return assembly.DetectTargetFrameworkId() ?? string.Empty;
}
+ public async Task GetRuntimePackAsync()
+ {
+ var assembly = await GetPEFileAsync().ConfigureAwait(false);
+ return assembly.DetectRuntimePack() ?? string.Empty;
+ }
+
public ReferenceLoadInfo LoadedAssemblyReferencesInfo { get; } = new ReferenceLoadInfo();
IDebugInfoProvider? debugInfoProvider;
@@ -614,6 +620,7 @@ namespace ICSharpCode.ILSpy
{
return LazyInitializer.EnsureInitialized(ref this.universalResolver, () => {
var targetFramework = this.GetTargetFrameworkIdAsync().Result;
+ var runtimePack = this.GetRuntimePackAsync().Result;
var readerOptions = DecompilerSettingsPanel.CurrentDecompilerSettings.ApplyWindowsRuntimeProjections
? MetadataReaderOptions.ApplyWindowsRuntimeProjections
@@ -622,7 +629,7 @@ namespace ICSharpCode.ILSpy
var rootedPath = Path.IsPathRooted(this.FileName) ? this.FileName : null;
return new UniversalAssemblyResolver(rootedPath, throwOnError: false, targetFramework,
- PEStreamOptions.PrefetchEntireImage, readerOptions);
+ runtimePack, PEStreamOptions.PrefetchEntireImage, readerOptions);
})!;
}
diff --git a/ILSpy/TreeNodes/ReferenceFolderTreeNode.cs b/ILSpy/TreeNodes/ReferenceFolderTreeNode.cs
index f42b0e765..987741cd1 100644
--- a/ILSpy/TreeNodes/ReferenceFolderTreeNode.cs
+++ b/ILSpy/TreeNodes/ReferenceFolderTreeNode.cs
@@ -56,7 +56,9 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
- language.WriteCommentLine(output, $"Detected Target-Framework-Id: {parentAssembly.LoadedAssembly.GetTargetFrameworkIdAsync().Result}");
+ language.WriteCommentLine(output, $"Detected TargetFramework-Id: {parentAssembly.LoadedAssembly.GetTargetFrameworkIdAsync().Result}");
+ language.WriteCommentLine(output, $"Detected RuntimePack: {parentAssembly.LoadedAssembly.GetRuntimePackAsync().Result}");
+
App.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(EnsureLazyChildren));
output.WriteLine();
language.WriteCommentLine(output, "Referenced assemblies (in metadata order):");