Browse Source

#2362: Provide more information on assembly resolve errors

pull/2373/head
Siegfried Pammer 4 years ago
parent
commit
2ed52b9634
  1. 2
      ICSharpCode.Decompiler/CSharp/ProjectDecompiler/TargetServices.cs
  2. 27
      ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs
  3. 37
      ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs

2
ICSharpCode.Decompiler/CSharp/ProjectDecompiler/TargetServices.cs

@ -250,7 +250,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
{ {
resolvedReference = assemblyResolver.Resolve(reference); resolvedReference = assemblyResolver.Resolve(reference);
} }
catch (AssemblyResolutionException) catch (ResolutionException)
{ {
resolvedReference = null; resolvedReference = null;
} }

27
ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs

@ -19,7 +19,6 @@
#nullable enable #nullable enable
using System; using System;
using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Reflection.Metadata; using System.Reflection.Metadata;
@ -29,19 +28,31 @@ using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.Metadata 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) public string? ModuleName { get; }
: this(reference, null)
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 ?? "<not found>"}", innerException)
{ {
this.Reference = reference ?? throw new ArgumentNullException(nameof(reference));
this.ResolvedFullPath = resolvedPath;
} }
public AssemblyResolutionException(IAssemblyReference reference, Exception? innerException) public ResolutionException(string mainModule, string moduleName, string? resolvedPath, Exception? innerException)
: base($"Failed to resolve assembly: '{reference}'", innerException) : base($"Failed to resolve module: '{moduleName} of {mainModule}'{Environment.NewLine}" +
$"Resolve result: {resolvedPath ?? "<not found>"}", innerException)
{ {
this.Reference = reference; this.MainModuleFullPath = mainModule ?? throw new ArgumentNullException(nameof(mainModule));
this.ModuleName = moduleName ?? throw new ArgumentNullException(nameof(moduleName));
this.ResolvedFullPath = resolvedPath;
} }
} }

37
ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs

@ -194,26 +194,41 @@ namespace ICSharpCode.Decompiler.Metadata
public PEFile Resolve(IAssemblyReference name) public PEFile Resolve(IAssemblyReference name)
{ {
var file = FindAssemblyFile(name); var file = FindAssemblyFile(name);
if (file == null) return CreatePEFileFromFileName(file, ex => new ResolutionException(name, file, ex));
{
if (throwOnError)
throw new AssemblyResolutionException(name);
return null;
}
return new PEFile(file, new FileStream(file, FileMode.Open, FileAccess.Read), streamOptions, metadataOptions);
} }
public PEFile ResolveModule(PEFile mainModule, string moduleName) public PEFile ResolveModule(PEFile mainModule, string moduleName)
{ {
string baseDirectory = Path.GetDirectoryName(mainModule.FileName); string baseDirectory = Path.GetDirectoryName(mainModule.FileName);
string moduleFileName = Path.Combine(baseDirectory, moduleName); 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<Exception?, Exception> makeException)
{
if (fileName == null)
{ {
if (throwOnError) if (throwOnError)
throw new Exception($"Module {moduleName} could not be found!"); throw makeException(null);
return 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<PEFile> ResolveAsync(IAssemblyReference name) public Task<PEFile> ResolveAsync(IAssemblyReference name)
@ -401,7 +416,7 @@ namespace ICSharpCode.Decompiler.Metadata
} }
if (throwOnError) if (throwOnError)
throw new AssemblyResolutionException(name); throw new ResolutionException(name, null, null);
return null; return null;
} }

Loading…
Cancel
Save