From 182c0988b40cba4cbafbd88d500f6fc7bef445c1 Mon Sep 17 00:00:00 2001 From: Philipp Feigl Date: Tue, 25 Sep 2018 18:26:38 +0200 Subject: [PATCH 1/3] feat(binding-redirect): add option to allow binding redirects via provided configuration file (#54) --- AsmSpy.CommandLine/ConsoleVisualizer.cs | 17 ++++++++++--- AsmSpy.CommandLine/Program.cs | 33 ++++++++++++++++++++++--- AsmSpy.CommandLine/packages.config | 8 +++--- AsmSpy.Core/AssemblyReferenceInfo.cs | 5 +++- AsmSpy.Core/DependencyAnalyzer.cs | 20 +++++++++------ README.md | 5 ++-- 6 files changed, 66 insertions(+), 22 deletions(-) diff --git a/AsmSpy.CommandLine/ConsoleVisualizer.cs b/AsmSpy.CommandLine/ConsoleVisualizer.cs index 7b12634..d20ecef 100644 --- a/AsmSpy.CommandLine/ConsoleVisualizer.cs +++ b/AsmSpy.CommandLine/ConsoleVisualizer.cs @@ -1,8 +1,9 @@ -using System; +using AsmSpy.Core; + +using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; -using AsmSpy.Core; namespace AsmSpy.CommandLine { @@ -10,6 +11,7 @@ public class ConsoleVisualizer : IDependencyVisualizer { private const ConsoleColor AssemblyNotFoundColor = ConsoleColor.Red; private const ConsoleColor AssemblyLocalColor = ConsoleColor.Green; + private const ConsoleColor AssemblyLocalRedirectedColor = ConsoleColor.DarkGreen; private const ConsoleColor AssemblyGlobalAssemblyCacheColor = ConsoleColor.Yellow; private const ConsoleColor AssemblyUnknownColor = ConsoleColor.Magenta; @@ -53,7 +55,7 @@ public virtual void Visualize() Console.WriteLine(AsmSpy_CommandLine.Detailing_only_conflicting_assembly_references); } - var assemblyGroups = _analyzerResult.Assemblies.Values.GroupBy(x => x.AssemblyName); + var assemblyGroups = _analyzerResult.Assemblies.Values.GroupBy(x => x.RedirectedAssemblyName); foreach (var assemblyGroup in assemblyGroups.OrderBy(i => i.Key.Name)) { @@ -118,7 +120,14 @@ protected virtual ConsoleColor GetMainNameColor(IList ass } else { - mainNameColor = AssemblyLocalColor; + if (assemblyReferenceInfoList.All(x => x.AssemblyName.FullName == x.RedirectedAssemblyName.FullName)) + { + mainNameColor = AssemblyLocalColor; + } + else + { + mainNameColor = AssemblyLocalRedirectedColor; + } } return mainNameColor; } diff --git a/AsmSpy.CommandLine/Program.cs b/AsmSpy.CommandLine/Program.cs index 384a11e..8d9d4ad 100644 --- a/AsmSpy.CommandLine/Program.cs +++ b/AsmSpy.CommandLine/Program.cs @@ -1,10 +1,12 @@ -using System; +using AsmSpy.Core; + +using Microsoft.Extensions.CommandLineUtils; + +using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; -using AsmSpy.Core; -using Microsoft.Extensions.CommandLineUtils; namespace AsmSpy.CommandLine { @@ -22,6 +24,7 @@ public static void Main(string[] args) var bindingRedirect = commandLineApplication.Option("-b|--bindingredirect", "Create binding-redirects", CommandOptionType.NoValue); var referencedStartsWith = commandLineApplication.Option("-rsw|--referencedstartswith", "Referenced Assembly should start with . Will only analyze assemblies if their referenced assemblies starts with the given value.", CommandOptionType.SingleValue); var includeSubDirectories = commandLineApplication.Option("-i|--includesub", "Include subdirectories in search", CommandOptionType.NoValue); + var configurationFile = commandLineApplication.Option("-c|--configurationFile", "Use the binding redirects of the given configuration file (Web.config or App.config)", CommandOptionType.SingleValue); commandLineApplication.HelpOption("-? | -h | --help"); commandLineApplication.OnExecute(() => @@ -37,6 +40,13 @@ public static void Main(string[] args) return -1; } + var configurationFilePath = configurationFile.Value(); + if (!string.IsNullOrEmpty(configurationFilePath) && !File.Exists(configurationFilePath)) + { + consoleLogger.LogMessage(string.Format(CultureInfo.InvariantCulture, "Directory or file: '{0}' does not exist.", configurationFilePath)); + return -1; + } + var isFilePathProvided = false; var fileName = ""; if (File.Exists(directoryOrFilePath)) @@ -63,8 +73,23 @@ public static void Main(string[] args) fileList = directoryInfo.GetFiles("*.dll", searchPattern).Concat(directoryInfo.GetFiles("*.exe", searchPattern)).ToList(); consoleLogger.LogMessage(string.Format(CultureInfo.InvariantCulture, "Check assemblies in: {0}", directoryInfo)); } + + AppDomain appDomainWithBindingRedirects = null; + try + { + var domaininfo = new AppDomainSetup + { + ConfigurationFile = configurationFilePath + }; + appDomainWithBindingRedirects = AppDomain.CreateDomain("AppDomainWithBindingRedirects", null, domaininfo); + } + catch (Exception ex) + { + consoleLogger.LogError($"Failed creating AppDomain from configuration file with message {ex.Message}"); + return -1; + } - IDependencyAnalyzer analyzer = new DependencyAnalyzer(fileList); + IDependencyAnalyzer analyzer = new DependencyAnalyzer(fileList, appDomainWithBindingRedirects); var result = analyzer.Analyze(consoleLogger); diff --git a/AsmSpy.CommandLine/packages.config b/AsmSpy.CommandLine/packages.config index 612f0a5..5f74d6e 100644 --- a/AsmSpy.CommandLine/packages.config +++ b/AsmSpy.CommandLine/packages.config @@ -1,5 +1,5 @@ - - - - + + + + \ No newline at end of file diff --git a/AsmSpy.Core/AssemblyReferenceInfo.cs b/AsmSpy.Core/AssemblyReferenceInfo.cs index e6d833b..93296ff 100644 --- a/AsmSpy.Core/AssemblyReferenceInfo.cs +++ b/AsmSpy.Core/AssemblyReferenceInfo.cs @@ -6,6 +6,7 @@ namespace AsmSpy.Core { public class AssemblyReferenceInfo : IAssemblyReferenceInfo { + #region Fields private readonly HashSet _references = new HashSet(); @@ -18,6 +19,7 @@ public class AssemblyReferenceInfo : IAssemblyReferenceInfo public virtual Assembly ReflectionOnlyAssembly { get; set; } public virtual AssemblySource AssemblySource { get; set; } public virtual AssemblyName AssemblyName { get; } + public virtual AssemblyName RedirectedAssemblyName { get; } public virtual ICollection ReferencedBy => _referencedBy.ToArray(); public virtual ICollection References => _references.ToArray(); public bool IsSystem => AssemblyInformationProvider.IsSystemAssembly(AssemblyName); @@ -26,9 +28,10 @@ public class AssemblyReferenceInfo : IAssemblyReferenceInfo #region Constructor - public AssemblyReferenceInfo(AssemblyName assemblyName) + public AssemblyReferenceInfo(AssemblyName assemblyName, AssemblyName redirectedAssemblyName) { AssemblyName = assemblyName; + RedirectedAssemblyName = redirectedAssemblyName; } #endregion diff --git a/AsmSpy.Core/DependencyAnalyzer.cs b/AsmSpy.Core/DependencyAnalyzer.cs index b9ae684..bb88bca 100644 --- a/AsmSpy.Core/DependencyAnalyzer.cs +++ b/AsmSpy.Core/DependencyAnalyzer.cs @@ -1,10 +1,11 @@ -using System; +using AsmSpy.Core.Native; + +using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; -using AsmSpy.Core.Native; namespace AsmSpy.Core { @@ -14,25 +15,30 @@ public class DependencyAnalyzer : IDependencyAnalyzer public virtual IEnumerable Files { get; } + protected virtual AppDomain AppDomainWithBindingRedirects { get; } + #endregion #region Analyze Support - public DependencyAnalyzer(IEnumerable files) + public DependencyAnalyzer(IEnumerable files, AppDomain appDomainWithBindingRedirects = null) { Files = files; + AppDomainWithBindingRedirects = appDomainWithBindingRedirects; } - private static AssemblyReferenceInfo GetAssemblyReferenceInfo(IDictionary assemblies, AssemblyName assemblyName) + private AssemblyReferenceInfo GetAssemblyReferenceInfo(IDictionary assemblies, AssemblyName assemblyName) { + var assemblyFullName = AppDomainWithBindingRedirects != null ? AppDomainWithBindingRedirects.ApplyPolicy(assemblyName.FullName) : assemblyName.FullName; + AssemblyReferenceInfo assemblyReferenceInfo; - if (assemblies.TryGetValue(assemblyName.FullName, out assemblyReferenceInfo)) + if (assemblies.TryGetValue(assemblyFullName, out assemblyReferenceInfo)) { return assemblyReferenceInfo; } - assemblyReferenceInfo = new AssemblyReferenceInfo(assemblyName); - assemblies.Add(assemblyName.FullName, assemblyReferenceInfo); + assemblyReferenceInfo = new AssemblyReferenceInfo(assemblyName, new AssemblyName(assemblyFullName)); + assemblies.Add(assemblyFullName, assemblyReferenceInfo); return assemblyReferenceInfo; } diff --git a/README.md b/README.md index fad9c74..8fd17a3 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ AsmSpy A simple command line tool to view assembly references. -## Install +## Install Install [from Chocolatey package](https://chocolatey.org/packages/asmspy): @@ -31,6 +31,7 @@ It will output a list of all conflicting assembly references. That is where diff | dgml | export dependency graph to a dgml file.
Supported formats: -dg \, --silent \ | | rsw | Will only analyze assemblies if their referenced assemblies starts with the given value.
Supported formats: -rsw \, --referencedstartswith \ | | i | include subdirectories in search.
Supported formats: -i, --includesub | +| c | use the binding redirects of the given configuration file (Web.config or App.config)
Supported formats: -c|--configurationFile | ### Examples To see a list of all assemblies and all references, just add the 'all' flag: @@ -64,7 +65,7 @@ The output looks something like this: 3.5.0.0 by Microsoft.Web.Mvc -You can see that System.Web.Mvc is referenced by 7 assemblies in my bin folder. Some reference +You can see that System.Web.Mvc is referenced by 7 assemblies in my bin folder. Some reference version 2.0.0.0 and some version 3.0.0.0. I can now resolve any conflicts. Color coding is used to more easily distinguish any problems. From e5dffa115862969417bd11e4ba7cf6f2d20dd472 Mon Sep 17 00:00:00 2001 From: Philipp Feigl Date: Wed, 26 Sep 2018 08:36:38 +0200 Subject: [PATCH 2/3] feat(fail-on-error): Added option to return negativ exit code on missing assemblies --- AsmSpy.CommandLine/Program.cs | 275 ++++++++++++----------- AsmSpy.Core/DependencyAnalyzerResult.cs | 3 + AsmSpy.Core/IDependencyAnalyzerResult.cs | 1 + 3 files changed, 144 insertions(+), 135 deletions(-) diff --git a/AsmSpy.CommandLine/Program.cs b/AsmSpy.CommandLine/Program.cs index 8d9d4ad..90c0262 100644 --- a/AsmSpy.CommandLine/Program.cs +++ b/AsmSpy.CommandLine/Program.cs @@ -1,135 +1,140 @@ -using AsmSpy.Core; - -using Microsoft.Extensions.CommandLineUtils; - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; - -namespace AsmSpy.CommandLine -{ - public static class Program - { - public static void Main(string[] args) - { - var commandLineApplication = new CommandLineApplication(throwOnUnexpectedArg: true); - var directoryOrFile = commandLineApplication.Argument("directoryOrFile", "The directory to search for assemblies or file path to a single assembly"); - var dgmlExport = commandLineApplication.Option("-dg|--dgml ", "Export to a dgml file", CommandOptionType.SingleValue); - var nonsystem = commandLineApplication.Option("-n|--nonsystem", "Ignore 'System' assemblies", CommandOptionType.NoValue); - var all = commandLineApplication.Option("-a|--all", "List all assemblies and references.", CommandOptionType.NoValue); - var noconsole = commandLineApplication.Option("-nc|--noconsole", "Do not show references on console.", CommandOptionType.NoValue); - var silent = commandLineApplication.Option("-s|--silent", "Do not show any message, only warnings and errors will be shown.", CommandOptionType.NoValue); - var bindingRedirect = commandLineApplication.Option("-b|--bindingredirect", "Create binding-redirects", CommandOptionType.NoValue); - var referencedStartsWith = commandLineApplication.Option("-rsw|--referencedstartswith", "Referenced Assembly should start with . Will only analyze assemblies if their referenced assemblies starts with the given value.", CommandOptionType.SingleValue); - var includeSubDirectories = commandLineApplication.Option("-i|--includesub", "Include subdirectories in search", CommandOptionType.NoValue); - var configurationFile = commandLineApplication.Option("-c|--configurationFile", "Use the binding redirects of the given configuration file (Web.config or App.config)", CommandOptionType.SingleValue); - - commandLineApplication.HelpOption("-? | -h | --help"); - commandLineApplication.OnExecute(() => - { - var consoleLogger = new ConsoleLogger(!silent.HasValue()); - - var directoryOrFilePath = directoryOrFile.Value; - var directoryPath = directoryOrFile.Value; - - if (!File.Exists(directoryOrFilePath) && !Directory.Exists(directoryOrFilePath)) - { - consoleLogger.LogMessage(string.Format(CultureInfo.InvariantCulture, "Directory or file: '{0}' does not exist.", directoryOrFilePath)); - return -1; - } - - var configurationFilePath = configurationFile.Value(); - if (!string.IsNullOrEmpty(configurationFilePath) && !File.Exists(configurationFilePath)) - { - consoleLogger.LogMessage(string.Format(CultureInfo.InvariantCulture, "Directory or file: '{0}' does not exist.", configurationFilePath)); - return -1; - } - - var isFilePathProvided = false; - var fileName = ""; - if (File.Exists(directoryOrFilePath)) - { - isFilePathProvided = true; - fileName = Path.GetFileName(directoryOrFilePath); - directoryPath = Path.GetDirectoryName(directoryOrFilePath); - } - - var onlyConflicts = !all.HasValue(); - var skipSystem = nonsystem.HasValue(); - var searchPattern = includeSubDirectories.HasValue() ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; - - var directoryInfo = new DirectoryInfo(directoryPath); - - List fileList; - if (isFilePathProvided) - { - fileList = directoryInfo.GetFiles(fileName, SearchOption.TopDirectoryOnly).ToList(); - consoleLogger.LogMessage(string.Format(CultureInfo.InvariantCulture, "Check assemblies referenced in: {0}", directoryOrFilePath)); - } - else - { - fileList = directoryInfo.GetFiles("*.dll", searchPattern).Concat(directoryInfo.GetFiles("*.exe", searchPattern)).ToList(); - consoleLogger.LogMessage(string.Format(CultureInfo.InvariantCulture, "Check assemblies in: {0}", directoryInfo)); - } - - AppDomain appDomainWithBindingRedirects = null; - try - { - var domaininfo = new AppDomainSetup - { - ConfigurationFile = configurationFilePath - }; - appDomainWithBindingRedirects = AppDomain.CreateDomain("AppDomainWithBindingRedirects", null, domaininfo); - } - catch (Exception ex) - { - consoleLogger.LogError($"Failed creating AppDomain from configuration file with message {ex.Message}"); - return -1; - } - - IDependencyAnalyzer analyzer = new DependencyAnalyzer(fileList, appDomainWithBindingRedirects); - - var result = analyzer.Analyze(consoleLogger); - - if (!noconsole.HasValue()) - { - IDependencyVisualizer visualizer = new ConsoleVisualizer(result) { SkipSystem = skipSystem, OnlyConflicts = onlyConflicts, ReferencedStartsWith = referencedStartsWith.HasValue() ? referencedStartsWith.Value() : string.Empty }; - visualizer.Visualize(); - } - - if (dgmlExport.HasValue()) - { - IDependencyVisualizer export = new DgmlExport(result, string.IsNullOrWhiteSpace(dgmlExport.Value()) ? Path.Combine(directoryInfo.FullName, "references.dgml") : dgmlExport.Value(), consoleLogger) { SkipSystem = skipSystem }; - export.Visualize(); - } - - if (bindingRedirect.HasValue()) - { - // binding redirect export explicitly doesn't respect SkipSystem - IDependencyVisualizer bindingRedirects = new BindingRedirectExport(result, string.IsNullOrWhiteSpace(dgmlExport.Value()) ? Path.Combine(directoryInfo.FullName, "bindingRedirects.xml") : dgmlExport.Value(), consoleLogger); - bindingRedirects.Visualize(); - } - - return 0; - }); - try - { - if (args == null || args.Length == 0) - { - commandLineApplication.ShowHelp(); - } - else - { - commandLineApplication.Execute(args); - } - } - catch (CommandParsingException cpe) - { - Console.WriteLine(cpe.Message); - commandLineApplication.ShowHelp(); - } - } - } -} +using AsmSpy.Core; + +using Microsoft.Extensions.CommandLineUtils; + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; + +namespace AsmSpy.CommandLine +{ + public static class Program + { + public static int Main(string[] args) + { + var commandLineApplication = new CommandLineApplication(throwOnUnexpectedArg: true); + var directoryOrFile = commandLineApplication.Argument("directoryOrFile", "The directory to search for assemblies or file path to a single assembly"); + var dgmlExport = commandLineApplication.Option("-dg|--dgml ", "Export to a dgml file", CommandOptionType.SingleValue); + var nonsystem = commandLineApplication.Option("-n|--nonsystem", "Ignore 'System' assemblies", CommandOptionType.NoValue); + var all = commandLineApplication.Option("-a|--all", "List all assemblies and references.", CommandOptionType.NoValue); + var noconsole = commandLineApplication.Option("-nc|--noconsole", "Do not show references on console.", CommandOptionType.NoValue); + var silent = commandLineApplication.Option("-s|--silent", "Do not show any message, only warnings and errors will be shown.", CommandOptionType.NoValue); + var bindingRedirect = commandLineApplication.Option("-b|--bindingredirect", "Create binding-redirects", CommandOptionType.NoValue); + var referencedStartsWith = commandLineApplication.Option("-rsw|--referencedstartswith", "Referenced Assembly should start with . Will only analyze assemblies if their referenced assemblies starts with the given value.", CommandOptionType.SingleValue); + var includeSubDirectories = commandLineApplication.Option("-i|--includesub", "Include subdirectories in search", CommandOptionType.NoValue); + var configurationFile = commandLineApplication.Option("-c|--configurationFile", "Use the binding redirects of the given configuration file (Web.config or App.config)", CommandOptionType.SingleValue); + var failOnMissing = commandLineApplication.Option("-f|--failOnMissing", "Whether to exit with an error code when AsmSpy detected Assemblies which could not be found", CommandOptionType.NoValue); + + commandLineApplication.HelpOption("-? | -h | --help"); + commandLineApplication.OnExecute(() => + { + var consoleLogger = new ConsoleLogger(!silent.HasValue()); + + var directoryOrFilePath = directoryOrFile.Value; + var directoryPath = directoryOrFile.Value; + + if (!File.Exists(directoryOrFilePath) && !Directory.Exists(directoryOrFilePath)) + { + consoleLogger.LogMessage(string.Format(CultureInfo.InvariantCulture, "Directory or file: '{0}' does not exist.", directoryOrFilePath)); + return -1; + } + + var configurationFilePath = configurationFile.Value(); + if (!string.IsNullOrEmpty(configurationFilePath) && !File.Exists(configurationFilePath)) + { + consoleLogger.LogMessage(string.Format(CultureInfo.InvariantCulture, "Directory or file: '{0}' does not exist.", configurationFilePath)); + return -1; + } + + var isFilePathProvided = false; + var fileName = ""; + if (File.Exists(directoryOrFilePath)) + { + isFilePathProvided = true; + fileName = Path.GetFileName(directoryOrFilePath); + directoryPath = Path.GetDirectoryName(directoryOrFilePath); + } + + var onlyConflicts = !all.HasValue(); + var skipSystem = nonsystem.HasValue(); + var searchPattern = includeSubDirectories.HasValue() ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; + + var directoryInfo = new DirectoryInfo(directoryPath); + + List fileList; + if (isFilePathProvided) + { + fileList = directoryInfo.GetFiles(fileName, SearchOption.TopDirectoryOnly).ToList(); + consoleLogger.LogMessage(string.Format(CultureInfo.InvariantCulture, "Check assemblies referenced in: {0}", directoryOrFilePath)); + } + else + { + fileList = directoryInfo.GetFiles("*.dll", searchPattern).Concat(directoryInfo.GetFiles("*.exe", searchPattern)).ToList(); + consoleLogger.LogMessage(string.Format(CultureInfo.InvariantCulture, "Check assemblies in: {0}", directoryInfo)); + } + + AppDomain appDomainWithBindingRedirects = null; + try + { + var domaininfo = new AppDomainSetup + { + ConfigurationFile = configurationFilePath + }; + appDomainWithBindingRedirects = AppDomain.CreateDomain("AppDomainWithBindingRedirects", null, domaininfo); + } + catch (Exception ex) + { + consoleLogger.LogError($"Failed creating AppDomain from configuration file with message {ex.Message}"); + return -1; + } + + IDependencyAnalyzer analyzer = new DependencyAnalyzer(fileList, appDomainWithBindingRedirects); + + var result = analyzer.Analyze(consoleLogger); + + if (!noconsole.HasValue()) + { + IDependencyVisualizer visualizer = new ConsoleVisualizer(result) { SkipSystem = skipSystem, OnlyConflicts = onlyConflicts, ReferencedStartsWith = referencedStartsWith.HasValue() ? referencedStartsWith.Value() : string.Empty }; + visualizer.Visualize(); + } + + if (dgmlExport.HasValue()) + { + IDependencyVisualizer export = new DgmlExport(result, string.IsNullOrWhiteSpace(dgmlExport.Value()) ? Path.Combine(directoryInfo.FullName, "references.dgml") : dgmlExport.Value(), consoleLogger) { SkipSystem = skipSystem }; + export.Visualize(); + } + + if (bindingRedirect.HasValue()) + { + // binding redirect export explicitly doesn't respect SkipSystem + IDependencyVisualizer bindingRedirects = new BindingRedirectExport(result, string.IsNullOrWhiteSpace(dgmlExport.Value()) ? Path.Combine(directoryInfo.FullName, "bindingRedirects.xml") : dgmlExport.Value(), consoleLogger); + bindingRedirects.Visualize(); + } + + if (failOnMissing.HasValue() && result.HasMissingAssemblies) + { + return -1; + } + return 0; + }); + try + { + if (args == null || args.Length == 0) + { + commandLineApplication.ShowHelp(); + return 0; + } + + return commandLineApplication.Execute(args); + } + catch (CommandParsingException cpe) + { + Console.WriteLine(cpe.Message); + commandLineApplication.ShowHelp(); + return 0; + } + } + } +} diff --git a/AsmSpy.Core/DependencyAnalyzerResult.cs b/AsmSpy.Core/DependencyAnalyzerResult.cs index 4c78f13..a858ce2 100644 --- a/AsmSpy.Core/DependencyAnalyzerResult.cs +++ b/AsmSpy.Core/DependencyAnalyzerResult.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; namespace AsmSpy.Core { @@ -20,5 +21,7 @@ public DependencyAnalyzerResult(ICollection analyzedFiles, IDictionary public ICollection AnalyzedFiles { get; } public IDictionary Assemblies { get; } + + public bool HasMissingAssemblies => Assemblies.Any(x => x.Value.AssemblySource == AssemblySource.NotFound); } } diff --git a/AsmSpy.Core/IDependencyAnalyzerResult.cs b/AsmSpy.Core/IDependencyAnalyzerResult.cs index 2d0c7dd..908bba0 100644 --- a/AsmSpy.Core/IDependencyAnalyzerResult.cs +++ b/AsmSpy.Core/IDependencyAnalyzerResult.cs @@ -7,5 +7,6 @@ public interface IDependencyAnalyzerResult { ICollection AnalyzedFiles { get; } IDictionary Assemblies { get; } + bool HasMissingAssemblies { get; } } } \ No newline at end of file From c8d5255bff8886cbfaae545b74ea3454ac3dbf0c Mon Sep 17 00:00:00 2001 From: Philipp Feigl Date: Wed, 26 Sep 2018 08:40:26 +0200 Subject: [PATCH 3/3] Small fix to documentation and addition of "fail-on-missing" option --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8fd17a3..112ab6e 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,8 @@ It will output a list of all conflicting assembly references. That is where diff | dgml | export dependency graph to a dgml file.
Supported formats: -dg \, --silent \ | | rsw | Will only analyze assemblies if their referenced assemblies starts with the given value.
Supported formats: -rsw \, --referencedstartswith \ | | i | include subdirectories in search.
Supported formats: -i, --includesub | -| c | use the binding redirects of the given configuration file (Web.config or App.config)
Supported formats: -c|--configurationFile | +| c | use the binding redirects of the given configuration file (Web.config or App.config)
Supported formats: -c \, --configurationFile \ | +| f | whether to exit with an error code when AsmSpy detected Assemblies which could not be found
Supported formats. -f, --failOnMissing | ### Examples To see a list of all assemblies and all references, just add the 'all' flag: