Skip to content

Commit

Permalink
feat(binding-redirect): add option to allow binding redirects via pro…
Browse files Browse the repository at this point in the history
…vided configuration file (mikehadlow#54)
  • Loading branch information
pfeigl committed Sep 25, 2018
1 parent 33d4df6 commit 182c098
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 22 deletions.
17 changes: 13 additions & 4 deletions AsmSpy.CommandLine/ConsoleVisualizer.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
using System;
using AsmSpy.Core;

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using AsmSpy.Core;

namespace AsmSpy.CommandLine
{
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;

Expand Down Expand Up @@ -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))
{
Expand Down Expand Up @@ -118,7 +120,14 @@ protected virtual ConsoleColor GetMainNameColor(IList<AssemblyReferenceInfo> ass
}
else
{
mainNameColor = AssemblyLocalColor;
if (assemblyReferenceInfoList.All(x => x.AssemblyName.FullName == x.RedirectedAssemblyName.FullName))
{
mainNameColor = AssemblyLocalColor;
}
else
{
mainNameColor = AssemblyLocalRedirectedColor;
}
}
return mainNameColor;
}
Expand Down
33 changes: 29 additions & 4 deletions AsmSpy.CommandLine/Program.cs
Original file line number Diff line number Diff line change
@@ -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
{
Expand All @@ -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 <string>. 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(() =>
Expand All @@ -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))
Expand All @@ -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);

Expand Down
8 changes: 4 additions & 4 deletions AsmSpy.CommandLine/packages.config
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ILMerge" version="2.14.1208" targetFramework="net462" />
<package id="Microsoft.Extensions.CommandLineUtils" version="1.1.0" targetFramework="net452" />
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ILMerge" version="2.14.1208" targetFramework="net462" />
<package id="Microsoft.Extensions.CommandLineUtils" version="1.1.0" targetFramework="net462" />
</packages>
5 changes: 4 additions & 1 deletion AsmSpy.Core/AssemblyReferenceInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace AsmSpy.Core
{
public class AssemblyReferenceInfo : IAssemblyReferenceInfo
{

#region Fields

private readonly HashSet<IAssemblyReferenceInfo> _references = new HashSet<IAssemblyReferenceInfo>();
Expand All @@ -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<IAssemblyReferenceInfo> ReferencedBy => _referencedBy.ToArray();
public virtual ICollection<IAssemblyReferenceInfo> References => _references.ToArray();
public bool IsSystem => AssemblyInformationProvider.IsSystemAssembly(AssemblyName);
Expand All @@ -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
Expand Down
20 changes: 13 additions & 7 deletions AsmSpy.Core/DependencyAnalyzer.cs
Original file line number Diff line number Diff line change
@@ -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
{
Expand All @@ -14,25 +15,30 @@ public class DependencyAnalyzer : IDependencyAnalyzer

public virtual IEnumerable<FileInfo> Files { get; }

protected virtual AppDomain AppDomainWithBindingRedirects { get; }

#endregion

#region Analyze Support

public DependencyAnalyzer(IEnumerable<FileInfo> files)
public DependencyAnalyzer(IEnumerable<FileInfo> files, AppDomain appDomainWithBindingRedirects = null)
{
Files = files;
AppDomainWithBindingRedirects = appDomainWithBindingRedirects;
}

private static AssemblyReferenceInfo GetAssemblyReferenceInfo(IDictionary<string, AssemblyReferenceInfo> assemblies, AssemblyName assemblyName)
private AssemblyReferenceInfo GetAssemblyReferenceInfo(IDictionary<string, AssemblyReferenceInfo> 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;
}

Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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):

Expand All @@ -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.<br> Supported formats: -dg \<filename\>, --silent \<filename\> |
| rsw | Will only analyze assemblies if their referenced assemblies starts with the given value.<br> Supported formats: -rsw \<string\>, --referencedstartswith \<string\> |
| i | include subdirectories in search.<br> Supported formats: -i, --includesub |
| c | use the binding redirects of the given configuration file (Web.config or App.config) <br> Supported formats: -c|--configurationFile |

### Examples
To see a list of all assemblies and all references, just add the 'all' flag:
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit 182c098

Please sign in to comment.