2008-10-22 26 views
36

我正在編寫一個工具來報告有關.NET應用程序在我的客戶端系統中部署的環境和區域的信息。如何爲反射操作加載.NET程序集並隨後卸載它?

我想讀取這些程序集中的程序集屬性的值。

這可以通過使用Assembly.ReflectionOnlyLoad來實現,但是即使這種方法也可以使程序集加載。這裏的問題是我無法從不同的路徑加載兩個具有相同名稱的程序集,所以自然我無法比較在不同系統中部署的相同應用程序。

在這一點上,我假設解決方案將涉及使用臨時AppDomain s。

有人可以詳細說明如何將程序集加載到另一個AppDomain,從中讀取屬性,然後卸載AppDomain

這需要適用於文件系統上的程序集以及URL地址上的程序集。

回答

47

MSDN documentation of System.Reflection.Assembly.ReflectionOnlyLoad (String)

的只反射上下文沒有 從其他上下文不同。 加載到 上下文中的程序集只能由卸載應用程序域的 卸載。

所以,恐怕卸載程序集的唯一方法是卸載應用程序域。 要創建一個新的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 
} 
+0

謝謝,這看起來像一個有用的模式。 – 2009-01-07 09:28:32

+1

Assembly.RefrectionOnlyLoad(...)是否仍然在當前域中加載程序集,而不是在TemporaryAppDomain中? – Anzurio 2009-05-30 18:59:58

+3

AZ:否。AppDomain.DoCallback「執行由指定委託標識的另一個應用程序域中的代碼」(MSDN)。 Assembly的文檔。ReflectionOnlyLoad明確指出「程序集加載到調用者應用程序域的僅反射上下文」(再次,MSDN)。這意味着程序集確實已加載到臨時應用程序域。 – 2009-05-30 20:15:57

4

你可以嘗試使用Unmanaged Metadata API,這是COM,可以很容易地從.NET應用程序以某種包裝的使用。

3

您必須使用應用程序域,沒有其他方式來卸載程序集。基本上,你必須使用這樣的代碼:

 

AppDomain tempDomain = AppDomain.CreateDomain("Temp Domain"); 
tempDomain.Load(assembly); 
AppDomain.Unload(tempDomain); 

9

雖然不是真正的卸載組件,如果你只是試圖讓你可以使用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; } 
1

您可以創建新的AppDomain的實例,該實例中執行代碼。

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; 
    } 
} 
相關問題