2012-06-15 4 views
4

Можно ли перечислять все установленные версии сборки в GAC с помощью C#? Например, у меня есть сборка с именем «My.Assembly». Сборка может поставляться в различных версиях («1.0.0.0», «2.3.4.5», «0.1.2.4», ...) и может быть скомпилирована для разных платформ (x86, x64, Any CPU).Перечислить все установленные версии сборки (в GAC)

Теперь мне нужно определить, какая из версий/платформ установлена.

Я знаю, что я мог перечислять каталоги в GAC, но это кажется неправильным. Должен быть лучший способ сделать это.

Background У меня есть приложение запуска, в котором пользователь выбирает DLL. Пусковая установка извлекает некоторую информацию из DLL (без ее загрузки), а затем запускает правильное управляемое приложение C#, которое обрабатывает DLL. DLL может быть скомпилирована для Win32 или x64 put предоставляет всегда один и тот же (независимый от платформы) интерфейс. Я использую функцию LoadLibrary для загрузки DLL в приложение C#. Единственная проблема заключается в том, что этот процесс должен соответствовать формату (x86 или x64). Приложение C# может и должно быть скомпилировано для x86, x64 и Any CPU.

+1

Вы делаете это с помощью Fusion api, CreateAssemblyEnum() и IAssemblyEnum + IAssemblyName. Это не отображается в .NET Framework, но оно * содержит * код для него. ILSpy или Reflector будут удобны. –

+0

@ HansPassant Fusions, похоже, именно то, что я искал. Кажется, трудно использовать. Было бы хорошо, если бы была управляемая/встроенная поддержка такого рода вещей. Большое спасибо! – Korexio

ответ

3

Использование managed wrapper для Unmanaged Fusion API был в состоянии сделать то, что я хотел бы сделать:

class Program 
{ 

    static IEnumerable<AssemblyName> GetInstalledVersions(string name) 
    { 
     int result; 

     IAssemblyName assemblyName; 
     result = Utils.CreateAssemblyNameObject(out assemblyName, name, CreateAssemblyNameObjectFlags.CANOF_DEFAULT, IntPtr.Zero); 
     if ((result != 0) || (assemblyName == null)) 
      throw new Exception("CreateAssemblyNameObject failed."); 

     IAssemblyEnum enumerator; 
     result = Utils.CreateAssemblyEnum(out enumerator, IntPtr.Zero, assemblyName, AssemblyCacheFlags.GAC, IntPtr.Zero); 
     if ((result != 0) || (enumerator == null)) 
      throw new Exception("CreateAssemblyEnum failed."); 

     while ((enumerator.GetNextAssembly(IntPtr.Zero, out assemblyName, 0) == 0) && (assemblyName != null)) 
     { 
      StringBuilder displayName = new StringBuilder(1024); 
      int displayNameLength = displayName.Capacity; 
      assemblyName.GetDisplayName(displayName, ref displayNameLength, (int)AssemblyNameDisplayFlags.ALL); 
      yield return new AssemblyName(displayName.ToString()); 
     } 

    } 

    static void Main(string[] args) 
    { 
     foreach (AssemblyName assemblyName in GetInstalledVersions("System.Data")) 
      Console.WriteLine("{0} V{1}, {2}", 
       assemblyName.Name, assemblyName.Version.ToString(), assemblyName.ProcessorArchitecture); 
    } 
} 

Запуск программы выше, дает мне следующий вывод:

System.Data V2.0.0.0, Amd64 
System.Data V2.0.0.0, X86 
System.Data V4.0.0.0, Amd64 
System.Data V4.0.0.0, X86 

Благодаря Hans Passant который указал мне в правильном направлении!

+0

Примечание: если оболочка слияния скомпилирована для Framework 2.0, она не вернет результаты, которые существуют в глобальном кеше сборок для версии CLR версии 4. –

Смежные вопросы