Версия файла и версия сборки
У меня есть библиотека .NET (FW 2.0), которая используется приложением COM (vb6), а также приложением .NET.
TLB, сгенерированный для COM, регистрируется как версия, состоящая из первых двух цифр "версии сборки". Например, версия сборки 1.2.5.7 становится версией 1.2 TLB. Это очень неудобно, потому что иногда я хотел бы изменить вторую цифру без необходимости перекомпилировать приложение vb6, но кажется, что мне нужно перекомпилировать, когда TLB изменения в версии.
Итак, я начал исследовать файл / сборку и попытался использовать версию файла для идентификации моих изменений, сохраняя постоянную версию сборки.
Это работает, как и ожидалось (т. е. это просто работает) с приложением .NET, но не так с vb6 one. Если какая-либо из третьих цифр отличается (например, сборка версии 1.0.0.0 / файл версии 1.0.2.0), каждый раз, когда я пытаюсь создать новый объект, я получаю "ошибка автоматизации -2147024894 (0x80070002)".
Может ли кто-нибудь скажите мне, почему это происходит,и есть ли обходной путь?
Edit: извините, код ошибки был неправильным. Я не знаю, откуда взялся этот 438-й, но готов поклясться, что видел его где-то поблизости...
Edit (2010-09-14): Как ни странно, если я компилирую с ассемблером версии 1.0.0.0, то я получил "ошибку автоматизации", даже если я перекомпилирую проект vb6.
Edit (2010-09-14, снова): после проверки с помощью ProcMon и FileMon, похоже, нет никакого доступа к файлам в оскорбительный код, только запросы реестра, большинство из которых относятся к другим версиям DLL. Похоже, что он пробует все предыдущие версии от 1.0.0.0 (которая является самой новой) до 1.0.1.3, но не следующую (1.0.2.0). Версия файла, прямо сейчас, 1.0.2.1, и это работает, если я установлю версию сборки 1.0.2.1, перекомпилирую и зарегистрирую ее.
Редактирование (2010-09-15): Есть три ошибки PATH_NOT_FOUND при поиске версии 1.0.1.3 моей .Объем библиотеки DLL в GAC (в c:windowsassemblyGAC_32, c:windowsassemblyGAC_MSIL и c:windowsassemblyGAC )
Есть некоторые другие ошибки (NAME_NOT_FOUND, в основном), но, кажется, найти все из них после попытки нескольких вариантов. Проблема, кажется, в том, что он ищет неправильную версию DLL.
Еще одно редактирование (2010-09-15, все еще): следуя совету Ханса Пассанта, я запустил оскорбительный код с fuslogvw, выполняющимся в фоновом режиме, и это важные линии, которые он бросает:
LOG: DisplayName = E_DataIndex, Version=1.0.1.3, Culture=нейтральный,
PublicKeyToken=c322af271028978e
(Полностью определенный)
LOG: Appbase = file:/ / / C: / Archivos de programa / Microsoft Visual
Studio / VB98 /
LOG: AppName = VB6.EXE
LOG: неудачный поиск в GAC.
Edit: согласно ответу Ганса, я рано связываюсь и изменился каждый Guid интерфейса. Это, кажется, работает (да, я знаю, я должен был попробовать это раньше)...
Edit (2010-09-17): я нашел причину первоначальной проблемы: я не отменял регистрацию TLB перед регистрацией нового и, поскольку я не изменял UUID, он продолжает искать последнюю установленную версию.
Конечно, моя система управления версиями не самая лучшая в мире, но, зная эти подводные камни, я буду продолжать ее использовать (я довольно новичок в COM и .NET interop).
Как "типы не совпадают", похоже, еще одна, не связанная с этим проблема, я удаляю информацию и, если мне не удастся решить ее самостоятельно, я открою новый вопрос.
2 ответов:
Управление версиями в COM-это серьезный вопрос. Страшный DLL-ад всегда находится за углом. Одно из самых жестких правил заключается в том, что если вы изменяете открытый интерфейс вашего COM-компонента, то вы должны дать интерфейсу новый GUID. Это гарантирует, что клиент, скомпилированный с предыдущей версией библиотеки типов, не сможет случайно использовать новый интерфейс.
Несоблюдение этого правила приводит к тому, что Очень трудно диагностировать проблемы. Клиент компании сервер вызовет неправильный метод. Или правильный метод, но с неправильными аргументами. Результат никогда не бывает приятным, все может случиться. Если Вам повезет, то программа завершит работу с помощью AccessViolation. Такого рода удачу трудно получить, хотя, как правило, она просто неисправна очень непостижимым образом.
Судя по вашему вопросу, вы не используете атрибут [Guid] в своих интерфейсах, но оставляете его компилятору для автоматической генерации. Он делает это, рассматривая, например, атрибут [AssemblyVersion]. Другая версия автоматически генерирует другой GUID. Что дальше, действительно, DLL Hell avoidance на работе, ваша программа VB6 больше не может найти интерфейс. Вы получите предсказуемое сообщение об ошибке вместо случайного вызова, идущего в сорняки. Программа VB6 должна быть перекомпилирована, чтобы использовать новую библиотеку типов.
Обратите внимание, что это в значительной степени функция, а не ошибка. Вы можете взять его под свой контроль, предоставив интерфейсам [Guid] атрибут, чтобы они больше не зависели от имени сборки или версии. Теперь вы должны вручную изменить его при изменении интерфейса. И заплатит за это рано или поздно, когда вы забудете сделать это.
Номер версии библиотеки типов также важен. Изменение публичного интерфейса-это Не простое изменение сборки или ревизии, это радикальное изменение. Клиенты вашего COM-сервера должны быть перекомпилированы. Выразите это в номере своей версии, увеличьте либо младший или старший номер версии.
Это компилируется/выполняется на 64-разрядной машине Windows 7?
Перейдите в окно свойств проекта и попробуйте переключить "целевую платформу" с "любого процессора "на"x86"
Попробуйте запустить reg cleaning tool, например CCleaner, и удалите все записи реестра, указывающие на dll. У меня был редкий случай, когда два ключа с соответствующими сигами попадали в реестр и вручную отменяли регистрацию/регистрацию нужных компонентов, пока плохие ключи не были очищены. Ссылки в проект VS выглядел правильно (вы могли просматривать нужные файлы и добавлять их без ошибок), но на самом деле указывали на "призрачные файлы" из плохого раздела реестра и умирали каждый раз, когда проект запускался/компилировался.
Comments