From 2ed52b96348e2596727fb1a97a11ddfa34de0f64 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 16 Apr 2021 14:06:23 +0200 Subject: [PATCH] #2362: Provide more information on assembly resolve errors --- .../ProjectDecompiler/TargetServices.cs | 2 +- .../Metadata/AssemblyReferences.cs | 27 ++++++++++---- .../Metadata/UniversalAssemblyResolver.cs | 37 +++++++++++++------ 3 files changed, 46 insertions(+), 20 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/TargetServices.cs b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/TargetServices.cs index ba9397aa7..790736474 100644 --- a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/TargetServices.cs +++ b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/TargetServices.cs @@ -250,7 +250,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler { resolvedReference = assemblyResolver.Resolve(reference); } - catch (AssemblyResolutionException) + catch (ResolutionException) { resolvedReference = null; } diff --git a/ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs b/ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs index f70e6ba0f..9ef8ee654 100644 --- a/ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs +++ b/ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs @@ -19,7 +19,6 @@ #nullable enable using System; -using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Metadata; @@ -29,19 +28,31 @@ using System.Threading.Tasks; namespace ICSharpCode.Decompiler.Metadata { - public sealed class AssemblyResolutionException : FileNotFoundException + public sealed class ResolutionException : Exception { - public IAssemblyReference Reference { get; } + public IAssemblyReference? Reference { get; } - public AssemblyResolutionException(IAssemblyReference reference) - : this(reference, null) + public string? ModuleName { get; } + + public string? MainModuleFullPath { get; } + + public string? ResolvedFullPath { get; } + + public ResolutionException(IAssemblyReference reference, string? resolvedPath, Exception? innerException) + : base($"Failed to resolve assembly: '{reference}'{Environment.NewLine}" + + $"Resolve result: {resolvedPath ?? ""}", innerException) { + this.Reference = reference ?? throw new ArgumentNullException(nameof(reference)); + this.ResolvedFullPath = resolvedPath; } - public AssemblyResolutionException(IAssemblyReference reference, Exception? innerException) - : base($"Failed to resolve assembly: '{reference}'", innerException) + public ResolutionException(string mainModule, string moduleName, string? resolvedPath, Exception? innerException) + : base($"Failed to resolve module: '{moduleName} of {mainModule}'{Environment.NewLine}" + + $"Resolve result: {resolvedPath ?? ""}", innerException) { - this.Reference = reference; + this.MainModuleFullPath = mainModule ?? throw new ArgumentNullException(nameof(mainModule)); + this.ModuleName = moduleName ?? throw new ArgumentNullException(nameof(moduleName)); + this.ResolvedFullPath = resolvedPath; } } diff --git a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs index cc32ba8f2..f6aebf1a1 100644 --- a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs +++ b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs @@ -194,26 +194,41 @@ namespace ICSharpCode.Decompiler.Metadata public PEFile Resolve(IAssemblyReference name) { var file = FindAssemblyFile(name); - if (file == null) - { - if (throwOnError) - throw new AssemblyResolutionException(name); - return null; - } - return new PEFile(file, new FileStream(file, FileMode.Open, FileAccess.Read), streamOptions, metadataOptions); + return CreatePEFileFromFileName(file, ex => new ResolutionException(name, file, ex)); } public PEFile ResolveModule(PEFile mainModule, string moduleName) { string baseDirectory = Path.GetDirectoryName(mainModule.FileName); string moduleFileName = Path.Combine(baseDirectory, moduleName); - if (!File.Exists(moduleFileName)) + return CreatePEFileFromFileName(moduleFileName, ex => new ResolutionException(mainModule.FileName, moduleName, moduleFileName, ex)); + } + + private PEFile CreatePEFileFromFileName(string fileName, Func makeException) + { + if (fileName == null) { if (throwOnError) - throw new Exception($"Module {moduleName} could not be found!"); + throw makeException(null); return null; } - return new PEFile(moduleFileName, new FileStream(moduleFileName, FileMode.Open, FileAccess.Read), streamOptions, metadataOptions); + + try + { + FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read); + return new PEFile(fileName, stream, streamOptions, metadataOptions); + } + catch (BadImageFormatException ex) + { + if (throwOnError) + throw makeException(ex); + } + catch (IOException ex) + { + if (throwOnError) + throw makeException(ex); + } + return null; } public Task ResolveAsync(IAssemblyReference name) @@ -401,7 +416,7 @@ namespace ICSharpCode.Decompiler.Metadata } if (throwOnError) - throw new AssemblyResolutionException(name); + throw new ResolutionException(name, null, null); return null; }