/// <summary> /// Get the list of types in a loaded assembly. /// </summary> /// <param name="assemblyDetails">The assembly details.</param> /// <returns>Returns the list of types. Returns null if the assembly is not found.</returns> internal ReadOnlyCollection <TypeDetails> GetTypes(AssemblyDetails assemblyDetails) { if (!assemblyDetails.IsDotNetAssembly) { return(new ReadOnlyCollection <TypeDetails>(new List <TypeDetails>())); } var loadedAssemblies = GetAssembliesInternal(); var loadedAssembly = loadedAssemblies.FirstOrDefault(a => assemblyDetails.Name == a.Assembly.GetName().Name&& assemblyDetails.Version == a.Assembly.GetName().Version.ToString() && (string.IsNullOrEmpty(assemblyDetails.Culture) ? "neutral" : assemblyDetails.Culture) == (string.IsNullOrEmpty(a.Assembly.GetName().CultureName) ? "neutral" : a.Assembly.GetName().CultureName)); if (loadedAssembly == null) { return(null); } if (string.IsNullOrWhiteSpace(loadedAssembly.Assembly.Location)) { _assemblyResolutionDirectory = null; } else { _assemblyResolutionDirectory = new FileInfo(loadedAssembly.Assembly.Location).Directory; } var types = new ReadOnlyCollection <Type>(loadedAssembly.Assembly.GetExportedTypes().ToList()); var details = new List <TypeDetails>(); foreach (var type in types) { details.Add(new TypeDetails { Assembly = assemblyDetails, Name = type.Name, Namespace = type.Namespace, IsClass = type.IsClass, IsGenericType = type.IsGenericType, IsGenericTypeDefinition = type.IsGenericTypeDefinition, IsInterface = type.IsInterface, IsPublic = type.IsPublic, IsValueType = type.IsValueType, IsStatic = type.IsAbstract && type.IsSealed, IsAbstract = type.IsAbstract }); } _assemblyResolutionDirectory = null; return(details.AsReadOnly()); }
/// <summary> /// Attempt to load the specified Assembly from its full name or location on the hard drive. /// </summary> /// <param name="assemblyDetails">The assembly's informations</param> /// <param name="forReflectionPurpose">Defines whether the assembly must be load for reflection only or also execution.</param> internal void LoadAssembly(AssemblyDetails assemblyDetails, bool forReflectionPurpose) { if (!assemblyDetails.IsDotNetAssembly) { if (!forReflectionPurpose && File.Exists(assemblyDetails.Location)) { var handler = NativeMethods.LoadLibrary(assemblyDetails.Location); if (handler == IntPtr.Zero) { int errorCode = Marshal.GetLastWin32Error(); throw new Exception($"Failed to load library '{Path.GetFileName(assemblyDetails.Location)}' (ErrorCode: {errorCode})"); } _win32ModuleHandlers.Add(handler); } return; } var assemblies = GetAssembliesInternal(); var assemblyLoaded = false; Assembly assembly = null; if (File.Exists(assemblyDetails.Location)) { assembly = assemblies.SingleOrDefault(asm => string.Compare(asm.Assembly.Location, assemblyDetails.Location, StringComparison.OrdinalIgnoreCase) == 0)?.Assembly; if (assembly == null) { assemblyLoaded = true; if (forReflectionPurpose) { assembly = Assembly.ReflectionOnlyLoadFrom(assemblyDetails.Location); } else { assembly = Assembly.LoadFrom(assemblyDetails.Location); } } } else { assembly = assemblies.SingleOrDefault(asm => string.Compare(asm.Assembly.FullName, assemblyDetails.FullName, StringComparison.OrdinalIgnoreCase) == 0)?.Assembly; if (assembly == null) { assemblyLoaded = true; if (forReflectionPurpose) { assembly = Assembly.ReflectionOnlyLoad(assemblyDetails.FullName); } else { assembly = Assembly.Load(assemblyDetails.FullName); } assemblyDetails.Location = assembly.Location; } } if (assemblyLoaded) { _explicitLoadedAssemblies.Add(new LoadedAssemblyDetails { Assembly = assembly, Details = assemblyDetails }); } }
/// <summary> /// Get the list of types in a loaded assembly. /// </summary> /// <param name="assemblyDetails">The assembly details.</param> /// <returns>Returns the list of types. Returns null if the assembly is not found.</returns> public ReadOnlyCollection <TypeDetails> GetTypes(AssemblyDetails assemblyDetails) { Requires.NotNull(assemblyDetails, nameof(assemblyDetails)); return(_assemblyManager.GetTypes(assemblyDetails)); }
/// <summary> /// Attempt to load the specified Assembly from its full name or location on the hard drive. /// </summary> /// <param name="assemblyDetails">The assembly's information</param> /// <param name="forReflectionPurpose">(optional) Defines whether the assembly must be load for reflection only or also execution. By default, the value is true.</param> public void LoadAssembly(AssemblyDetails assemblyDetails, bool forReflectionPurpose = true) { Requires.NotNull(assemblyDetails, nameof(assemblyDetails)); _assemblyManager.LoadAssembly(assemblyDetails, forReflectionPurpose); }
/// <summary> /// Gets a new instance of <see cref="AssemblyDetails"/> filled from the full name or the location of an assembly. /// </summary> /// <param name="assemblyNameOrLocation">Defines the full name or the location of the assembly.</param> /// <returns>An instance of <see cref="AssemblyDetails"/></returns> public static AssemblyDetails GetAssemblyDetailsFromNameOrLocation(string assemblyNameOrLocation) { var details = new AssemblyDetails(); var fullName = string.Empty; if (File.Exists(assemblyNameOrLocation)) { details.Location = assemblyNameOrLocation; if (IsDotNetAssembly(assemblyNameOrLocation)) { var assemblyNameInfo = AssemblyName.GetAssemblyName(assemblyNameOrLocation); details.CopyToLocal = true; details.IsDotNetAssembly = true; fullName = assemblyNameInfo.FullName; } else { var windowsPath = Environment.GetFolderPath(Environment.SpecialFolder.Windows); if (!details.Location.StartsWith(windowsPath)) { details.CopyToLocal = true; } var fileVersionInfo = FileVersionInfo.GetVersionInfo(details.Location); fullName = $"{fileVersionInfo.FileDescription}, Version={fileVersionInfo.FileVersion}, Culture={fileVersionInfo.Language}"; } } else { details.IsDotNetAssembly = true; fullName = assemblyNameOrLocation; } var properties = fullName.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries); var name = properties.FirstOrDefault(); var version = properties.SingleOrDefault(p => p.StartsWith(Consts.AssemblyPropertyVersion))?.Replace(Consts.AssemblyPropertyVersion, string.Empty); var culture = properties.SingleOrDefault(p => p.StartsWith(Consts.AssemblyPropertyCulture))?.Replace(Consts.AssemblyPropertyCulture, string.Empty); var publicKeyToken = properties.SingleOrDefault(p => p.StartsWith(Consts.AssemblyPropertyPublicKeyToken))?.Replace(Consts.AssemblyPropertyPublicKeyToken, string.Empty); var processorArchitecture = properties.SingleOrDefault(p => p.StartsWith(Consts.AssemblyPropertyProcessorArchitecture))?.Replace(Consts.AssemblyPropertyProcessorArchitecture, string.Empty); var custom = properties.SingleOrDefault(p => p.StartsWith(Consts.AssemblyPropertyCustom))?.Replace(Consts.AssemblyPropertyCustom, string.Empty); var processorArch = ProcessorArchitecture.None; switch (processorArchitecture) { case Consts.AssemblyPropertyX86: processorArch = ProcessorArchitecture.X86; break; case Consts.AssemblyPropertyX64: processorArch = ProcessorArchitecture.Amd64; break; case Consts.AssemblyPropertyAnyCPU: processorArch = ProcessorArchitecture.MSIL; break; default: break; } details.Culture = culture; details.Custom = custom; details.FullName = fullName; details.Name = name; details.ProcessorArchitecture = processorArch; details.PublicKeyToken = publicKeyToken; details.Version = version; return(details); }