如何加载reflection操作的.NET程序集,随后卸载它?
我正在编写一个工具来报告有关在我的客户端系统中部署的跨环境和区域的.NET应用程序的信息。
我想阅读这些程序集中的程序集属性的值。
这可以使用Assembly.ReflectionOnlyLoad
来实现,但是即使这种方法也能保持程序集的加载。 这里的问题是我不能加载两个具有相同名称的程序集,所以自然不能比较在不同系统中部署的相同应用程序。
在这一点上,我假设解决scheme将涉及使用临时AppDomain
的。
有人可以详细说明如何将程序集加载到另一个AppDomain
,从中读取属性,然后卸载AppDomain
?
这需要为文件系统上的程序集以及URL地址上的程序集起作用。
从System.Reflection.Assembly.ReflectionOnlyLoad(string)的MSDN文档 :
仅reflection背景与其他背景没有区别。 加载到上下文中的程序集只能通过卸载应用程序域来卸载。
所以,恐怕卸载程序集的唯一方法是卸载应用程序域。 要创build一个新的AppDomain并将其加载到它:
public void TempLoadAssembly() { AppDomain tempDomain = AppDomain.CreateDomain("TemporaryAppDomain"); tempDomain.DoCallBack(LoaderCallback); AppDomain.Unload(tempDomain); } private void LoaderCallback() { Assembly.ReflectionOnlyLoad("YourAssembly"); // Do your stuff here }
虽然不是真的卸载程序集,如果你只是想获得文件的版本号,你可以使用System.Diagnostics.FileVersionInfo
。
var info = FileVersionInfo.GetVersionInfo(path);
FileVersionInfo
具有以下属性:
public string Comments { get; } public string CompanyName { get; } public int FileBuildPart { get; } public string FileDescription { get; } public int FileMajorPart { get; } public int FileMinorPart { get; } public string FileName { get; } public int FilePrivatePart { get; } public string FileVersion { get; } public string InternalName { get; } public bool IsDebug { get; } public bool IsPatched { get; } public bool IsPreRelease { get; } public bool IsPrivateBuild { get; } public bool IsSpecialBuild { get; } public string Language { get; } public string LegalCopyright { get; } public string LegalTrademarks { get; } public string OriginalFilename { get; } public string PrivateBuild { get; } public int ProductBuildPart { get; } public int ProductMajorPart { get; } public int ProductMinorPart { get; } public string ProductName { get; } public int ProductPrivatePart { get; } public string ProductVersion { get; } public string SpecialBuild { get; }
您可以尝试使用非托pipe元数据API ,这是COM,可以很容易地从.NET应用程序与某种包装使用。
您必须使用应用程序域,没有其他方式来卸载程序集。 基本上你必须使用这样的代码:
AppDomain tempDomain = AppDomain.CreateDomain(“Temp Domain”); tempDomain.Load(组装); AppDomain.Unload(tempDomain);
您可以在新的AppDomain中创build一个实例,并在该实例中执行您的代码。
var settings = new AppDomainSetup { ApplicationBase = AppDomain.CurrentDomain.BaseDirectory, }; var childDomain = AppDomain.CreateDomain(Guid.NewGuid().ToString(), null, settings); var handle = Activator.CreateInstance(childDomain, typeof(ReferenceLoader).Assembly.FullName, typeof(ReferenceLoader).FullName, false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, null, CultureInfo.CurrentCulture, new object[0]); var loader = (ReferenceLoader)handle.Unwrap(); //This operation is executed in the new AppDomain var paths = loader.LoadReferences(assemblyPath); AppDomain.Unload(childDomain);
这是ReferenceLoader
public class ReferenceLoader : MarshalByRefObject { public string[] LoadReferences(string assemblyPath) { var assembly = Assembly.ReflectionOnlyLoadFrom(assemblyPath); var paths = assembly.GetReferencedAssemblies().Select(x => x.FullName).ToArray(); return paths; } }