在GAC

2009-10-21 33 views
11

列舉組件如何枚舉在C#中的GAC所有可用的組件?在GAC

其實我面臨着一個愚蠢的代碼問題 - 所謂Telerik.Web.UI.dll大會被稱爲在項目中使用 - 這個特殊的DLL是不存在的BIN文件夾中。應用程序在服務器上工作正常 - 但在我的機器上,顯然編譯器給出了錯誤。 Ex-Developer堅持認爲它不在服務器上的GAC中,而且「它就是這樣」。現在我需要檢查這個DLL是否在GAC中註冊。

幫助將不勝感激。

美好的一天;

+0

@effkey - 您是否設法解決此問題? – Kev 2010-02-05 17:43:59

+0

nop;我無法;而是我從山洪(相同版本)下載了.dll文件,他們工作。如果不在GAC中,我仍不明白ASP .NET從哪裏獲取DLLz。 – effkay 2010-02-06 09:52:38

回答

10

如果服務器有限的訪問,然後這可能工作:

// List of all the different types of GAC folders for both 32bit and 64bit 
// environments. 
List<string> gacFolders = new List<string>() { 
    "GAC", "GAC_32", "GAC_64", "GAC_MSIL", 
    "NativeImages_v2.0.50727_32", 
    "NativeImages_v2.0.50727_64", 
    "NativeImages_v4.0.30319_32", 
    "NativeImages_v4.0.30319_64" 
}; 

foreach (string folder in gacFolders) 
{ 
    string path = Path.Combine(
     Environment.ExpandEnvironmentVariables(@"%systemroot%\assembly"), 
     folder); 

    if(Directory.Exists(path)) 
    { 
     Response.Write("<hr/>" + folder + "<hr/>"); 

     string[] assemblyFolders = Directory.GetDirectories(path); 
     foreach (string assemblyFolder in assemblyFolders) 
     { 
      Response.Write(assemblyFolder + "<br/>"); 
     } 
    } 
} 

它基本上列舉的原料GAC文件夾。它適用於DiscountASP共享主機,因此可能適用於您的主機環境。

它可以通過枚舉深入到每一個組件的文件夾中抽出了版本號和公鑰標記加以點綴。

4

入住這codeproject GAC API Interface文章。這使用未記錄的fusion.dll來啓動GAC。但作者聲稱

此代碼已知與.NET 1.1和2.0一起使用。請注意DLL fusion.dll在1.1和 2.0中是不同的。因此,如果您安裝了兩個框架,請確保將代碼 指向正確的DLL。否則大多數 API調用將失敗。默認的 實現使用在WINDOWS目錄中的 中找到的那個。

+0

謝謝 - 將檢查;但我擔心這可能會導致權限問題;因爲我有限的訪問服務器 - 我懷疑ASP NET用戶下的功能。 但無論如何,我之前也看到了它,但排除了上述疑問。但是,讓我們試試看。 – effkay 2009-10-21 09:14:26

+1

它不是無證的。至少不再是。 https://support.microsoft.com/kb/317540或http://msdn.microsoft.com/en-us/library/ms404523.aspx – 2014-05-01 19:01:17

4

你並不真的需要寫在C#中的東西,以找出是否該特定DLL是在GAC。您可以使用gacutil.exe和命令行中的/ l選項列出GAC的內容。

+0

希望我可以 - 我有限的訪問服務器 - 即,FTP只:) 但仍然,感謝評論 – effkay 2009-10-21 09:33:19

+0

@effkay - 對不起,這沒有幫助。如果您對服務器的訪問權限有限,那麼代碼解決方案將如何提供幫助? – 2009-10-21 09:42:09

+0

@MikeTwo聽起來他計劃上傳一個網頁,列出GAC中的程序集。 – BrainSlugs83 2012-02-17 02:01:28

-3

可能是你需要GAC觀衆是這樣的:

alt text

Video: How to use Add GAC References Dialog

希望這有助於

小號

+0

這不會有幫助,因爲他說他只能通過FTP訪問服務器。他希望能夠使用在不完全信任環境中執行的C#代碼來枚舉GAC。 – BrainSlugs83 2012-02-17 02:12:13

3

如果是純簡ASP.NET網站,並且該程序集不在該站點的bin文件夾或服務器的GAC中(並且web.config中沒有任何可疑內容),也許該網站是某種子網站,並且該網站的其中一個較高層包含bin文件夾中的引用(或者web.config中的某些內容,因爲子網站/文件夾會繼承其父母的web.configs) ?現在

,如果您有該文件被加載正確的環境(這聽起來像你這樣做),你可以問.NET在哪裏了。DLL是從哪裏來的,並顯示代替,例如:

Assembly a = Assembly.Load("Microsoft.VisualStudio.Shell, Version=2.0.0.0, " 
      + "PublicKeyToken=b03f5f7f11d50a3a, Culture=Neutral"); 

Console.WriteLine(a.Location); 

會加載一個程序集,顯示其在磁盤上的位置,我的輸出是: C:\Windows\assembly\GAC_MSIL\Microsoft.VisualStudio.Shell\2.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.Shell.dll

如果是「C下:\ WINDOWS \程序集「,你知道它在GAC中。

如果您已經引用程序集,您可以在沒有Assembly.Load調用的情況下執行此操作,從而可以枚舉加載到當前app.domain中的程序集並僅打印出(或渲染到文字控件或Response.Write,等等......)他們的.Location屬性是什麼。

編輯: 操作的代碼看起來是這樣的:

foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) 
{ 
    Console.WriteLine(a.GetName().FullName); 
    Console.WriteLine(a.Location); 
    Console.WriteLine(); 
} 

編輯: 在一個充滿信任的環境,下面的代碼(控制檯應用程序)將枚舉GAC寫出來每個程序集都應該很容易將其修改爲ASP.NET應用程序,但我不確定它是否可以在不完全信任的環境中工作(只需在此猜測,您可能會很幸運):

static void ProcessFile(string file) 
{ 
    try 
    { 
     Assembly a = Assembly.LoadFile(file); 

     Console.WriteLine(a.GetName().FullName); 
    } 
    catch { /* do nothing */ } 
} 

static void ProcessFolder(string folder) 
{ 
    foreach (string file in Directory.GetFiles(folder)) 
    { 
     ProcessFile(file); 
    } 

    foreach (string subFolder in Directory.GetDirectories(folder)) 
    { 
     ProcessFolder(subFolder); 
    } 
} 

static void Main(string[] args) 
{ 
    ProcessFolder(@"C:\Windows\Assembly"); 
} 
3

一個簡單的方法來枚舉DLL文件的目錄

public static string[] GetGlobalAssemblyCacheFiles(string path) 
{ 
    List<string> files = new List<string>(); 

    DirectoryInfo di = new DirectoryInfo(path); 

    foreach (FileInfo fi in di.GetFiles("*.dll")) 
    { 
     files.Add(fi.FullName); 
    } 

    foreach (DirectoryInfo diChild in di.GetDirectories()) 
    { 
     var files2 = GetGlobalAssemblyCacheFiles(diChild.FullName); 
     files.AddRange(files2); 
    } 

    return files.ToArray(); 
} 

,你可以得到所有的文件

string gacPath = Environment.GetFolderPath(System.Environment.SpecialFolder.Windows) + "\\assembly"; 
var files = GetGlobalAssemblyCacheFiles(gacPath); 

如果需要加載每個組件,你得到了不同的運行時間異常版。出於這個原因,您可以使用Assembly.ReflectionOnlyLoadFrom加載程序集來僅以反射方式加載程序集。然後,程序集不加載你的AppDomain,不要拋出異常。

1

圖我還不如扔在我的基於LINQ的解決方案(方便的,如果你只是尋找一個單一的文件,並且不希望通過每個文件枚舉)

功能來查找文件:

public static IEnumerable<string> FindFiles (string path, string filter = "", int depth = int.MaxValue) { 
     DirectoryInfo di = new DirectoryInfo(path); 

     IEnumerable<string> results = (! string.IsNullOrEmpty(filter) ? di.GetFiles(filter) : di.GetFiles()).Select(f => f.FullName); 
     if (depth > 0) { 
      results = results.Concat(di.GetDirectories().SelectMany(d => FindFiles(d.FullName, filter, depth - 1))); 
     } 

     return results; 
    } 

而調用(我沒有Environment.SpecialFolder.Windows這樣使用Environment.SpecialFolder.System代替)

string path = Environment.GetFolderPath(Environment.SpecialFolder.System) + "\\..\\assembly"; 
foreach (string s in FindFiles(path, "*.dll")) { 
    Console.WriteLine(s); 
} 

此外,作爲FYI此方法enume對整個GAC進行評級,並且您可能在tmp /和temp /中找到重複的DLL,使用Tmp進行安裝,並使用Temp進行卸載。