2016-12-12 4 views
-1

В моей программе используются драйверы COM от стороннего производителя. Я пытаюсь реализовать переключение между различными версиями драйверов.Тип.GetTypeFromCLSID и Type.GetTypeFromProgID получить кешированный результат?

Сначала я попытался использовать DLL Interop, сгенерированный VS, и вызвал regsvr32 из кода. Я смог совершать звонки водителям через Assembly.Load и размышления, но казалось, что, несмотря на то, что я звонил в разные библиотеки Interop, я получал ту же версию. Я попробовал регистрацию и регистрацию библиотек через regsvr32 перед вызовом interops и попытался сделать задержку в случае, если regsvr32 работает медленно.

В конце концов я удалил библиотеки interop и решил работать непосредственно с COM. Обе версии драйверов имеют один и тот же CLSID. Я закончил с кодом, который просто пытается создать экземпляр COM-объекта и получить свойство, которое получает значение версии.

while (true) 
     { 
      var CLSID = new Guid("E4795281-3564-11D4-8E97-0080C87C930A"); 
      var type = Type.GetTypeFromCLSID(CLSID); 
      var obj = Activator.CreateInstance(type); 
      object propertyValue = type.InvokeMember("Version", System.Reflection.BindingFlags.GetProperty, null, obj, null); 
      Console.WriteLine(propertyValue); 
      Console.ReadKey(); 
     } 

Я запустил программу, а затем попытаюсь вручную зарегистрировать DLL. Независимо от того, как долго я жду после регистрации, моя программа создает версию, которую она получила в начале. Если я перезапущу программу - она ​​получит последнюю зарегистрированную версию. Я вижу, что запись в реестре изменяется, поэтому я думаю, что может быть проблема с кешированием.

Я попытался запустить код в отдельном AppDomain и воссоздал его, но это не помогло.

Я также пробовал использовать Type.GetTypeFromProgID с тем же результатом.

Любые предложения по обходному методу?

+0

Вам нужно отменить регистрацию первого перед загрузкой второго? Можете ли вы PInvoke и создать две разные подписи для двух DLL? – OrdinaryOrange

+0

@OrdinaryOrange Я попробовал отменить регистрацию, но это не имело никакого значения. Я не думаю, что это необходимо, поскольку регистрация отменяет предыдущие записи из того, что я вижу в реестре. Я не пытался использовать PInvoke, поскольку, если я правильно понял, мне потребовалось бы записать макет для обеих версий dll. Любые материалы, которые вы можете почитать, чтобы прочитать об использовании PInvoke? Насколько я понимаю, это не имеет ничего общего с COM, верно? Это просто еще один способ вызвать неуправляемые вещи. – netaholic

+0

Да, Pinvoke - это прямой вызов метода direct. Да, вы правы, вам нужен еще один слой. Это может быть болезненным для настройки управляемых подписей и является лишь идеей левого поля. Интересно, может ли SxS потренироваться, я напишу некоторые подробности. – OrdinaryOrange

ответ

0

Try Reg Free COM, я помню, где-то читал, что он хорошо справляется с несколькими версиями и избегает конфликтов.

Я предполагаю, что вы используете VS. Вернитесь к нормальному Interop. Добавьте COM-ссылки к проекту для автоматического создания интерфейсов взаимодействия. Затем щелкните правой кнопкой мыши ссылку на interop и установите Isolated = True. Убедитесь, что на данный момент у вас есть COM, зарегистрированный в реестре. Теперь скомпилируйте свою программу. Вы должны увидеть файл .manifest, сгенерированный в выходной папке вместе с .exe. Откройте манифест в блокноте и, надеюсь, у него есть обе библиотеки dll со всеми различными CLSID и TLIB. Отменить регистрацию всех COM-адресов из реестра (с помощью Regsvr32).

Теперь запустите приложение. В этом режиме контекст активации будет запрашивать .manifest для всех необходимых ресурсов, а не реестра, и, надеюсь, он должен затем правильно разрешить вызовы каждой версии dll.