Указание точных ссылочных версий в app.manifest

Реализуя использование ODP.Net в наших приложениях, я столкнулся с потенциальной проблемой с версиями, поэтому я запустил приложение для быстрого тестирования, чтобы посмотреть, повлияет ли оно на нас, и оно имело место.

У нас есть клиенты, которые имеют или хотят иметь наши приложения в Oracle, но они используют разные версии и, как правило, имеют корпоративный стандарт для версии Oracle Client, развернутой на их рабочих станциях. Наша идея состояла в том, чтобы развернуть фиксированную версию ODP плюс соответствующий мгновенный клиент с нашим приложением (в каталоге программы), поскольку Oracle гарантирует 2 основные версии совместимости с любой стороны для любой данной версии клиента, то есть мы можем работать, скажем, с Oracle 10.1 до теоретического Oracle 12 с использованием развертывания ODP и клиента 11.1.

Это нормально, но проблема возникает, если наши клиенты затем развернут более высокую версию Oracle Client, которая регистрирует более новую версию ODP в GAC, и политику издателя, которая предписывает приложениям использовать новую версию, несмотря ни на что. Мы используем пользовательскую реализацию одной библиотеки из EntlibContrib (оболочки ODP), созданной с использованием конкретной версии EL5 и ODP, которую мы используем, и развертывание более новой версии в GAC приводит к сбою, как доказано в тестовом приложении.

Чтобы проверить это, я использовал чистую виртуальную машину с установленной Win 7 x86, а затем добавил Oracle Client 10.2 (который зарегистрировал ODP 10.2 в GAC), и мое тестовое приложение использовало ODP и Client 11.1. Это работало нормально, поэтому я установил Клиент 11.2 с ODP, зарегистрированным в GAC, который также добавляет политики издателя, и это доказало, что тестовое приложение не будет работать.

Чтобы обойти это, я добавил запись зависимости в app.manifest, например:

  <dependency>
    <dependentAssembly>
      <assemblyIdentity
          type="win32"
          name="Oracle.DataAccess"
          version="2.111.7.20"
          processorArchitecture="x86"
          publicKeyToken="89b483f429c47342"
       />
    </dependentAssembly>
  </dependency>

Это соответствует версии и открытому ключу бинарного файла ODP, который мы развертываем, поэтому я ожидал, что тестовое приложение будет его использовать. Однако при запуске приложения я получил следующую ошибку:

The application has failed to start because its side-by-side configuration is incorrect.

И журнал событий содержит это:

Activation context generation failed for "C:\Program Files\OPT\OPT\OraclePerformanceTester.exe". Dependent Assembly Oracle.DataAccess,processorArchitecture="x86",publicKeyToken="89b483f429c47342",type="win32",version="2.111.7.20" could not be found. Please use sxstrace.exe for detailed diagnosis.

Используя sxstrace, я получил следующий вывод:

Begin Activation Context Generation.
Input Parameter:
    Flags = 0
    ProcessorArchitecture = x86
    CultureFallBacks = en-US;en
    ManifestPath = C:\Program Files\OPT\OPT\OraclePerformanceTester.exe
    AssemblyDirectory = C:\Program Files\OPT\OPT\
    Application Config File = C:\Program Files\OPT\OPT\OraclePerformanceTester.exe.Config

INFO: Parsing Application Config File C:\Program Files\OPT\OPT\OraclePerformanceTester.exe.Config.
INFO: Parsing Manifest File C:\Program Files\OPT\OPT\OraclePerformanceTester.exe.
INFO: Manifest Definition Identity is OraclePerformanceTester.exe,version="1.0.0.0".
INFO: Reference: Oracle.DataAccess,processorArchitecture="x86",publicKeyToken="89b483f429c47342",type="win32",version="2.111.7.20"
INFO: Resolving reference Oracle.DataAccess,processorArchitecture="x86",publicKeyToken="89b483f429c47342",type="win32",version="2.111.7.20".
INFO: Resolving reference for ProcessorArchitecture x86.
    INFO: Resolving reference for culture Neutral.
        INFO: Applying Binding Policy.
            INFO: No publisher policy found.
            INFO: No binding policy redirect found.
        INFO: Begin assembly probing.
            INFO: Did not find the assembly in WinSxS.
            INFO: Attempt to probe manifest at C:\Windows\assembly\GAC_32\Oracle.DataAccess\2.111.7.20__89b483f429c47342\Oracle.DataAccess.DLL.
            INFO: Attempt to probe manifest at C:\Program Files\OPT\OPT\Oracle.DataAccess.DLL.
            INFO: Attempt to probe manifest at C:\Program Files\OPT\OPT\Oracle.DataAccess.MANIFEST.
            INFO: Attempt to probe manifest at C:\Program Files\OPT\OPT\Oracle.DataAccess\Oracle.DataAccess.DLL.
            INFO: Attempt to probe manifest at C:\Program Files\OPT\OPT\Oracle.DataAccess\Oracle.DataAccess.MANIFEST.
            INFO: Did not find manifest for culture Neutral.
        INFO: End assembly probing.
ERROR: Cannot resolve reference Oracle.DataAccess,processorArchitecture="x86",publicKeyToken="89b483f429c47342",type="win32",version="2.111.7.20".
ERROR: Activation Context generation failed.

Указанный файл (Oracle.DataAccess.dll) существует в каталоге программы рядом с исполняемым файлом со всеми остальными зависимостями, но по какой-то причине он просто не подхватит его. Единственный манифест, который мне приходилось использовать ранее, был для проверок UAC на exe, который работал нормально, и, насколько я вижу, я выполнил шаги, чтобы указать точную версию, которая должна переопределять политику издателя. Что я сделал не так?

ура

1 ответ

Решение

Я собираюсь добавить ответ, так как Ганс Пассант (который дал мне ответ) не добавил официальный ответ, плюс я хочу расширить его, потому что ответ Ганса похож на другие, которые я нашел, но которые не были слишком ясны потому что они рассказывают только часть истории.

Добавление <publisherPolicy apply="no" /> в app.config действительно работает, но я нашел почти везде, где написано, что это не объясняет, куда в app.config он должен идти. Вы должны добавить это к <runtime> раздел, как это:

<configuration>
    <!--Other Sections-->
    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
             <!--Ensures Oracle Publisher Policies don't override the version of ODP being used.-->
                <assemblyIdentity name="Oracle.DataAccess" publicKeyToken="89B483F429C47342"/>
                <publisherPolicy apply="no"/>
              </dependentAssembly>
        </assemblyBinding>
    </runtime>
    <!--Other Sections-->
</configuration>

Конечно, вы должны изменить имя сборки и открытый ключ в соответствии с вашими потребностями. И это все. Мне дали бестолковую информацию из обычно надежного источника об использовании файлов манифеста, так что урок здесь состоит в том, чтобы дважды проверить вашу информацию, прежде чем тратить нагрузку в конце времени на пробную работу - это, вероятно, будет потрачено впустую.

Другие вопросы по тегам