private static void WriteMainNodeDependants(AssemblyDependencyNode mainNode, AssemblyDependencyGraph graph) { var mainNodeDependants = graph.GetDirectDependants(mainNode).OrderBy(x => x.Identity).ToList(); if (mainNodeDependants.Any()) { Logger.Information(Separator); Logger.Warning("WARNING: Detected that there are still some assemblies that depend on the main assembly. Try to avoid this scenario. Different binding redirects might be needed for them."); foreach (var node in mainNodeDependants) { Logger.Information("{AssemblyIdentity}", node.Identity); } } }
private static void WriteNodesOutsideMainDependencyTree(AssemblyDependencyNode mainNode, List <AssemblyDependencyNode> nodes, IList <AssemblyDependencyNode> allMainDependencies, AssemblyDependencyGraph graph) { var nodesOutsideOfDependencyTree = nodes .Where(x => x != mainNode && !allMainDependencies.Contains(x)) .Where(x => x.Loaded) .ToList(); if (nodesOutsideOfDependencyTree.Any()) { Logger.Information(Separator); Logger.Information("All assemblies that aren't in any way connected to the main, but were loaded:"); foreach (var node in nodesOutsideOfDependencyTree) { Logger.Information(Separator); Logger.Warning("{AssemblyIdentity}", node.Identity); var directDependants = graph.GetDirectDependants(node).ToList(); if (directDependants.Any()) { Logger.Information(""); Logger.Information("Nodes that depend on this assembly directly:"); foreach (var dependant in directDependants) { Logger.Information("{AssemblyIdentity}", dependant.Identity); } var indirectDependants = graph.GetIndirectDependants(node).ToList(); if (indirectDependants.Any()) { Logger.Information(""); Logger.Information("Nodes that depend on this assembly indirectly:"); foreach (var dependant in indirectDependants) { Logger.Information("{AssemblyIdentity}", dependant.Identity); } } } else { Logger.Information(""); Logger.Information("No nodes that depend on this were found."); } } } }
private static void WriteAssembliesNotLoaded(List <AssemblyDependencyNode> nodes, AssemblyDependencyGraph graph) { var nodesByGroup = nodes.ToLookup(x => x.Identity.Unversioned); var nodesNotLoaded = nodes.Where(node => !node.Loaded).ToList(); if (nodesNotLoaded.Any()) { Logger.Information(Separator); Logger.Information("Assemblies that couldn't be loaded:"); foreach (var node in nodesNotLoaded) { Logger.Information(Separator); if (node.Name != null) { Logger.Information("{AssemblyIdentity}", node.Identity); } else { Logger.Information("{File}", node.File.FullName); } Logger.Information(""); if (node.LoadedFromName == AssemblyLoadStatus.Failed) { Logger.Information("Couldn't load from assembly name. Exception message:"); Logger.Information(node.LoadedFromNameError.Message); } else if (node.LoadedFromFile == AssemblyLoadStatus.Failed) { Logger.Information("Couldn't load from file. Exception message:"); Logger.Information(node.LoadedFromFileError.Message); } else { throw new InvalidOperationException("Assembly not attempted to be loaded, something went wrong."); } var directDependants = graph.GetDirectDependants(node).ToList(); if (directDependants.Any()) { Logger.Information(""); Logger.Information("Nodes that depend on this assembly directly:"); foreach (var dependant in directDependants) { Logger.Information("{AssemblyIdentity}", dependant.Identity); } var indirectDependants = graph.GetIndirectDependants(node).ToList(); if (indirectDependants.Any()) { Logger.Information(""); Logger.Information("Nodes that depend on this assembly indirectly:"); foreach (var dependant in indirectDependants) { Logger.Information("{AssemblyIdentity}", dependant.Identity); } } } else { Logger.Information(""); Logger.Information("No nodes that depend on this were found."); } Logger.Information(""); Logger.Information("If this is an important reference, consider fixing this reference. Also make sure that you didn't omit it from the inputs."); var otherNodesInGroup = nodesByGroup[node.Identity.Unversioned].Where(x => x != node && x.Loaded).ToList(); if (otherNodesInGroup.Any()) { Logger.Information(""); Logger.Information("Other versions of this assembly were loaded:"); foreach (var otherVersionNode in otherNodesInGroup.OrderBy(x => x.Identity.Version)) { Logger.Information("{Version}", otherVersionNode.Identity.Version); } if (otherNodesInGroup.All(x => x.Identity.Version < node.Identity.Version)) { Logger.Warning("WARNING: This is the highest version of the assembly, yet it wasn't loaded. A downgrading binding redirect might be needed."); } } } } }
private static void WriteBindingRedirects(IList <AssemblyDependencyNode> allMainDependencies, AssemblyDependencyGraph graph) { var dependenciesGrouped = allMainDependencies .GroupBy(x => x.Identity.Unversioned) .Where(x => x.Count() > 1 && x.Any(y => y.Loaded)) .OrderBy(x => x.Key) .ToList(); if (dependenciesGrouped.Any()) { Logger.Information(Separator); Logger.Information("Recommended binding redirects:"); var dependentAssemblyTriples = new List <(AssemblyUnversionedIdentity Key, Version highestVersion, Version highestVersionLoaded)>(); foreach (var group in dependenciesGrouped) { Logger.Information(Separator); Logger.Information("{AssemblyName}", group.Key.ToString()); Logger.Information("--- Versions ---"); foreach (var node in group.OrderBy(x => x.Identity.Version)) { Logger.Information(""); if (node.Loaded) { Logger.Information("-- {Version} [Location=\"{Location}\"]", node.Identity.Version, node.File.FullName); } else { Logger.Warning("-- {Version} [Not Found]", node.Identity.Version); } var directDependants = graph.GetDirectDependants(node).ToList(); if (directDependants.Any()) { Logger.Information(""); Logger.Information("Nodes that depend on this version directly:"); foreach (var dependant in directDependants) { Logger.Information("{AssemblyIdentity}", dependant.Identity); } var indirectDependants = graph.GetIndirectDependants(node).ToList(); if (indirectDependants.Any()) { Logger.Information(""); Logger.Information("Nodes that depend on this version indirectly:"); foreach (var dependant in indirectDependants) { Logger.Information("{AssemblyIdentity}", dependant.Identity); } } } else { Logger.Information(""); Logger.Warning("No nodes that depend on this version were found."); } } var highestVersion = group.Max(x => x.Identity.Version); var highestVersionLoaded = group.Where(x => x.Loaded).Max(x => x.Identity.Version); var dependentAssemblyTriple = (group.Key, highestVersion, highestVersionLoaded); var element = GetAssemblyBindingXElement(dependentAssemblyTriple); Logger.Information(""); Logger.Information("--- Recommended redirect ---\n{Element}", element); if (highestVersionLoaded < highestVersion) { Logger.Warning("WARNING: Recommending a downgrading redirect."); } dependentAssemblyTriples.Add(dependentAssemblyTriple); } if (dependenciesGrouped.Count > 1) { Logger.Information(Separator); Logger.Information("Collected binding redirects:"); var element = GetAssemblyBindingXElement(dependentAssemblyTriples.ToArray()); Logger.Information("\n{Element}", element); } } else { Logger.Information(Separator); Logger.Information("No recommended binding redirects."); } }