Cmdlets/src/XpandPosh.Cmdlets/ResolveAssemblyDependencies/Resolve-AssemblyDependencies.cs
using System;
using System.Collections.Generic; using System.IO; using System.Linq; using System.Management.Automation; using System.Reflection; using System.Runtime.InteropServices; namespace XpandPosh.Cmdlets.ResolveAssemblyDependencies{ [Cmdlet(VerbsDiagnostic.Resolve, "AssemblyDependencies")] [CmdletBinding] public class ResolveAssemblyDependencies : PSCmdlet{ [Parameter(Mandatory = true,Position = 0)] public string AssemblyFile{ get; set; } public ResolveDependenciesOutputType OutputType{ get; set; } [Parameter(Position = 3)] public SwitchParameter SkipGAC{ get; set; } [Parameter(Position = 2)] public string[] Locations{ get; set; }=new string[0]; protected override void ProcessRecord(){ base.ProcessRecord(); var sources = Locations.Concat(new[]{Path.GetDirectoryName(AssemblyFile)}).ToArray(); Assembly ResolveEventHandler(object sender, ResolveEventArgs args){ var name = args.Name; var indexOf = name.IndexOf(",", StringComparison.Ordinal); if (indexOf > 0) name = args.Name.Substring(0, indexOf); foreach (var location in sources){ var path = $"{Path.Combine(location, name)}.dll"; if (File.Exists(path)) return Assembly.LoadFile(path); } return null; } AppDomain.CurrentDomain.AssemblyResolve += ResolveEventHandler; Resolve(); AppDomain.CurrentDomain.AssemblyResolve -= ResolveEventHandler; } private void Resolve(){ var references = new HashSet<string>(); var pending = new Queue<AssemblyName>(); pending.Enqueue(Assembly.LoadFile(AssemblyFile).GetName()); while (pending.Count > 0){ var assemblyName = pending.Dequeue(); var value = assemblyName.ToString(); if (references.Contains(value)){ continue; } references.Add(value); try{ var assembly = Assembly.Load(assemblyName); if (assembly != null){ foreach (var sub in assembly.GetReferencedAssemblies()){ pending.Enqueue(sub); } foreach (var type in assembly.GetTypes()){ foreach (var method in type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)){ var customAttribute = (DllImportAttribute) Attribute.GetCustomAttribute(method, typeof(DllImportAttribute)); if (customAttribute != null && !references.Contains(customAttribute.Value)){ references.Add(customAttribute.Value); } } } } } catch (Exception ex){ WriteError(new ErrorRecord(ex, ex.GetHashCode().ToString(), ErrorCategory.InvalidOperation, assemblyName.ToString())); } } var sortedRefs = references.OrderBy(s => s); if (OutputType == ResolveDependenciesOutputType.Assembly){ var assemblies = AppDomain.CurrentDomain.GetAssemblies() .Where(assembly => !SkipGAC || !assembly.GlobalAssemblyCache) .ToArray(); WriteObject(sortedRefs.Select(s => assemblies.FirstOrDefault(_ => _.GetName().ToString() == s)), true); } else if(OutputType==ResolveDependenciesOutputType.AssemblyName){ WriteObject(sortedRefs.Select(s => { var indexOf = s.IndexOf(",", StringComparison.Ordinal); return indexOf > -1 ? s.Substring(0, indexOf) : s; }),true); } else{ WriteObject(sortedRefs,true); } } } public enum ResolveDependenciesOutputType{ AssemblyName, AssemblyFullName, Assembly } } |