【问题标题】:Specifying Exact Reference Versions in app.manifest在 app.manifest 中指定准确的参考版本
【发布时间】:2012-05-12 04:03:58
【问题描述】:

在我们的应用程序中实现使用 ODP.Net 时,我遇到了版本的潜在问题,因此我敲开了一个快速测试应用程序,看看它是否会影响我们,结果确实如此。

我们有一些客户在 Oracle 上拥有或想要我们的应用,但他们使用不同的版本,而且他们通常对部署在其工作站上的 Oracle 客户端版本有一个公司标准。我们的想法是使用我们的应用程序(在程序目录中)部署一个固定版本的 ODP 以及适当的即时客户端,因为 Oracle 保证任何给定客户端版本的任一侧都有 2 个主要版本的兼容性,这意味着我们可以与 Oracle 合作10.1 到理论上的 Oracle 12,使用部署 ODP 和客户端 11.1。

这很好,但是如果我们的客户随后部署了更高版本的 Oracle 客户端,该客户端在 GAC 中注册了更新版本的 ODP,并且发布者策略告诉应用程序无论如何都使用新版本,那么问题就来了。我们正在使用来自 EntlibContrib(ODP 包装器)的一个库的自定义实现,该库使用我们使用的特定版本的 EL5 和 ODP 构建,并且将更新版本部署到 GAC 会导致此操作失败,正如测试应用程序所证明的那样。

为了对此进行测试,我使用了一个安装了 Win 7 x86 的干净 VM,然后添加了 Oracle Client 10.2(它在 GAC 中注册了 ODP 10.2)并让我的测试应用使用 ODP 和 Client 11.1。这很好,所以我安装了客户端 11.2,在 GAC 中注册了 ODP,它也添加了发布者策略,这证明测试应用程序会失败。

为了解决这个问题,我在 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) 存在于可执行文件旁边的程序目录中,具有所有其他依赖项,但由于某种原因它不会拾取它。我之前必须使用的唯一清单是对运行良好的 exe 进行 UAC 检查,据我所知,我已按照步骤指定应覆盖发布者策略的确切版本。我做错了什么?

干杯

【问题讨论】:

  • 这样的清单仅对存储在 Windows 并行缓存 (c:\windows\winsxs) 中的非托管程序集的依赖项有用。 .NET 框架已经使用 [AssemblyVersion] 对托管程序集执行此操作。它的并行缓存是 GAC。我不清楚你需要解决的实际问题。
  • 问题是我们试图绕过 GAC 中的发布者政策,该政策试图强制我们的应用使用与我们希望它使用的版本不同的 ODP 版本。该策略意味着我们的应用程序将不再使用程序目录中存在的引用库,因此在这种情况下(我被理解)清单的重点是确保应用程序选择所需的版本作为清单内容覆盖 GAC 中的任何内容。
  • 在你的 .config 文件中使用 ` 来禁用它。
  • @Hans - 这是一个正确的答案,我会接受它,因为(加上一些额外的东西)可以解决问题,谢谢。稍微挖掘一下,发现它是一个需要忽略策略的链下的 dll,所以我现在正在研究一种在 DLL 中获取嵌入式配置以执行此操作的方法,因为这个特定的 DLL 可能用于多个应用程序,这样就不必为每个配置添加一个新部分,但那是另一回事了。

标签: .net reference manifest gac publisher-policy


【解决方案1】:

我将添加一个答案,因为 Hans Passant(他给了我答案)没有添加官方答案,而且我想扩展它,因为 Hans 的答案与我找到的其他人相似,但不是不太清楚,因为它们只讲述了故事的一部分。

在 app.config 中添加 &lt;publisherPolicy apply="no" /&gt; 确实有效,但我发现几乎所有地方都说这并不能解释它应该在 app.config 中的 何处。您需要将其添加到 &lt;runtime&gt; 部分,如下所示:

<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>

当然,您必须根据需要更改程序集名称和公钥。就是这样。我从一个通常可靠的来源获得了有关使用清单文件的信息,所以这里的课程是在最后花费大量时间之前仔细检查您的信息。尝试一些东西的时间 - 这可能会浪费时间。

【讨论】:

    猜你喜欢
    • 2013-02-14
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 2019-02-23
    • 1970-01-01
    • 2017-03-23
    • 1970-01-01
    • 2010-11-16
    相关资源
    最近更新 更多