Skip to content

Commit

Permalink
Merge pull request mikehadlow#52 from yitzhaks/DgmlNonSystem
Browse files Browse the repository at this point in the history
DgmlExport should respect the --nonsystem flag
  • Loading branch information
mikehadlow authored Jul 27, 2018
2 parents 519e436 + 7e32992 commit 44a8a97
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 23 deletions.
19 changes: 9 additions & 10 deletions AsmSpy.CommandLine/BindingRedirectExport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ public void Visualize()
{
try
{
var document = Generate(_result, false);
var document = Generate(_result, skipSystem: false);
using (var writer = XmlWriter.Create(_exportFileName, new XmlWriterSettings{Indent = true}))
{
document.WriteTo(writer);
}
_logger.LogMessage(string.Format(CultureInfo.InvariantCulture, "Exported to file {0}", _exportFileName));
}
catch (System.UnauthorizedAccessException uae)
catch (UnauthorizedAccessException uae)
{
_logger.LogError(string.Format(CultureInfo.InvariantCulture, "Could not write file {0} due to error {1}", _exportFileName, uae.Message));
}
Expand All @@ -43,20 +43,19 @@ public void Visualize()
}
}

public static XmlDocument Generate(IDependencyAnalyzerResult result, bool skipSystem = false)
public static XmlDocument Generate(IDependencyAnalyzerResult result, bool skipSystem)
{
var document = new XmlDocument();
document.LoadXml(@"
<runtime>
<assemblyBinding xmlns=""urn: schemas - microsoft - com:asm.v1"">
</assemblyBinding>
</runtime>");
var assemblyGroups = result.Assemblies.Values.GroupBy(x => x.AssemblyName.Name);
foreach (var assemblyGroup in assemblyGroups.OrderBy(i => i.Key))
var assemblyGroups = result.Assemblies.Values.GroupBy(x => x.AssemblyName);

foreach (var assemblyGroup in assemblyGroups.OrderBy(i => i.Key.Name))
{
if (skipSystem &&
(assemblyGroup.Key.ToUpperInvariant().StartsWith("SYSTEM", StringComparison.OrdinalIgnoreCase) ||
assemblyGroup.Key.ToUpperInvariant().StartsWith("MSCORLIB", StringComparison.OrdinalIgnoreCase)))
if (skipSystem && AssemblyInformationProvider.IsSystemAssembly(assemblyGroup.Key))
{
continue;
}
Expand Down Expand Up @@ -96,7 +95,7 @@ public static XmlDocument Generate(IDependencyAnalyzerResult result, bool skipSy
assemblyIdentity.SetAttribute("publicKeyToken", publicKeyToken);
}
var cultureName = assemblyToUse.CultureName;
assemblyIdentity.SetAttribute("culture", cultureName == "" ? "neutral" : cultureName);
assemblyIdentity.SetAttribute("culture", string.IsNullOrEmpty(cultureName) ? "neutral" : cultureName);
depedententAssembly.AppendChild(assemblyIdentity);
var bindingRedirect = document.CreateElement("bindingRedirect");
bindingRedirect.SetAttribute("oldVersion", $"{lowestAssemblyVersion}-{highestAssemblyVersion}");
Expand All @@ -121,4 +120,4 @@ private static string GetPublicKeyTokenFromAssembly(AssemblyName assembly)
return publicKeyToken;
}
}
}
}
9 changes: 5 additions & 4 deletions AsmSpy.CommandLine/ConsoleVisualizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public class ConsoleVisualizer : IDependencyVisualizer
#region Properties

public bool OnlyConflicts { get; set; }

public bool SkipSystem { get; set; }

public string ReferencedStartsWith { get; set; }
Expand Down Expand Up @@ -52,16 +53,16 @@ public virtual void Visualize()
Console.WriteLine(AsmSpy_CommandLine.Detailing_only_conflicting_assembly_references);
}

var assemblyGroups = _analyzerResult.Assemblies.Values.GroupBy(x => x.AssemblyName.Name);
var assemblyGroups = _analyzerResult.Assemblies.Values.GroupBy(x => x.AssemblyName);

foreach (var assemblyGroup in assemblyGroups.OrderBy(i => i.Key))
foreach (var assemblyGroup in assemblyGroups.OrderBy(i => i.Key.Name))
{
if (SkipSystem && (assemblyGroup.Key.ToUpperInvariant().StartsWith("SYSTEM", StringComparison.OrdinalIgnoreCase) || assemblyGroup.Key.ToUpperInvariant().StartsWith("MSCORLIB", StringComparison.OrdinalIgnoreCase)))
if (SkipSystem && AssemblyInformationProvider.IsSystemAssembly(assemblyGroup.Key))
{
continue;
}

var assemblyInfos = assemblyGroup.OrderBy(x => x.AssemblyName.ToString()).ToList();
var assemblyInfos = assemblyGroup.OrderBy(x => x.AssemblyName.Name).ToList();
if (OnlyConflicts && assemblyInfos.Count <= 1)
{
if (assemblyInfos.Count == 1 && assemblyInfos[0].AssemblySource == AssemblySource.Local)
Expand Down
19 changes: 17 additions & 2 deletions AsmSpy.CommandLine/DgmlExport.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Globalization;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using AsmSpy.Core;
Expand All @@ -18,21 +19,35 @@ public DgmlExport(IDependencyAnalyzerResult result, string exportFileName, ILogg
_logger = logger;
}

#region Properties

public bool SkipSystem { get; set; }

#endregion

public void Visualize()
{
var nodes = new StringBuilder();

foreach (var assemblyReference in _result.Assemblies.Values)
{
if (SkipSystem && assemblyReference.IsSystem)
continue;

nodes.AppendFormat(CultureInfo.InvariantCulture, "<Node Id=\"{0}\" Label=\"{1}\" Category=\"Assembly\" />\n",
assemblyReference.AssemblyName.FullName, assemblyReference.AssemblyName.Name);
}

var links = new StringBuilder();
foreach (var assemblyReference in _result.Assemblies.Values)
{
if (SkipSystem && assemblyReference.IsSystem)
continue;

foreach (var referenceTo in assemblyReference.References)
{
if (SkipSystem && referenceTo.IsSystem)
continue;

links.AppendFormat(CultureInfo.InvariantCulture, "<Link Source=\"{0}\" Target=\"{1}\" Category=\"Reference\" />\n",
assemblyReference.AssemblyName.FullName, referenceTo.AssemblyName.FullName);
}
Expand Down
4 changes: 2 additions & 2 deletions AsmSpy.CommandLine/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,13 @@ public static void Main(string[] args)

if (dgmlExport.HasValue())
{

IDependencyVisualizer export = new DgmlExport(result, string.IsNullOrWhiteSpace(dgmlExport.Value()) ? Path.Combine(directoryInfo.FullName, "references.dgml") : dgmlExport.Value(), consoleLogger);
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();
}
Expand Down
1 change: 1 addition & 0 deletions AsmSpy.Core/AsmSpy.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyInformationProvider.cs" />
<Compile Include="AssemblyReferenceInfo.cs" />
<Compile Include="AssemblySource.cs" />
<Compile Include="DependencyAnalyzer.cs" />
Expand Down
37 changes: 37 additions & 0 deletions AsmSpy.Core/AssemblyInformationProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using System.Collections;
using System.Reflection;

namespace AsmSpy.Core
{
public static class AssemblyInformationProvider
{
private static readonly byte[] SystemPublicKeyToken = new byte[] { 183, 122, 92, 86, 25, 52, 224, 137 };

// some system assemblies are signed with this public key token, but some Microsoft non-system assemblies are signed with it too
////private static readonly byte[] MicrosoftPublicKeyToken = new byte[] { 49, 191, 56, 86, 173, 54, 78, 53 };

/// <summary>
/// Check whether the given assembly name is a system assembly or not.
/// </summary>
/// <remarks>
/// This ISN'T a security check, and shouldn't be used for security decisions.
/// Rather this relies on a heuristic and may be used to filter our system assemblies from the dependency graph.
/// </remarks>
/// <param name="assemblyName">The assembly name to check.</param>
/// <returns>true if the assembly name (probably) is a system assembly; otherwise, false.</returns>
public static bool IsSystemAssembly(AssemblyName assemblyName)
{
assemblyName = assemblyName ?? throw new ArgumentNullException(nameof(assemblyName));

// fairly reliable and easy to check
if (StructuralComparisons.StructuralEqualityComparer.Equals(assemblyName.GetPublicKeyToken(), SystemPublicKeyToken))
{
return true;
}

return assemblyName.Name.StartsWith("System", StringComparison.OrdinalIgnoreCase) ||
assemblyName.Name.StartsWith("mscorlib", StringComparison.OrdinalIgnoreCase);
}
}
}
9 changes: 5 additions & 4 deletions AsmSpy.Core/AssemblyReferenceInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public class AssemblyReferenceInfo : IAssemblyReferenceInfo
public virtual AssemblyName AssemblyName { get; }
public virtual ICollection<IAssemblyReferenceInfo> ReferencedBy => _referencedBy.ToArray();
public virtual ICollection<IAssemblyReferenceInfo> References => _references.ToArray();
public bool IsSystem => AssemblyInformationProvider.IsSystemAssembly(AssemblyName);

#endregion

Expand Down Expand Up @@ -61,12 +62,12 @@ public override int GetHashCode()

public override bool Equals(object obj)
{
var info = obj as IAssemblyReferenceInfo;
if (info == null)
if (obj is IAssemblyReferenceInfo info)
{
return false;
return info.AssemblyName.FullName == AssemblyName.FullName;
}
return info.AssemblyName.FullName == AssemblyName.FullName;

return false;
}

#endregion
Expand Down
3 changes: 2 additions & 1 deletion AsmSpy.Core/IAssemblyReferenceInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ public interface IAssemblyReferenceInfo
AssemblyName AssemblyName { get; }
ICollection<IAssemblyReferenceInfo> ReferencedBy { get; }
ICollection<IAssemblyReferenceInfo> References { get; }
bool IsSystem { get; }
void AddReference(IAssemblyReferenceInfo info);
void AddReferencedBy(IAssemblyReferenceInfo info);
}
}
}
1 change: 1 addition & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
version: 1.3.{build}
image: Visual Studio 2017
before_build:
- nuget restore
# enable patching of AssemblyInfo.* files
Expand Down

0 comments on commit 44a8a97

Please sign in to comment.