1

原谅我的编码员,因为我犯了罪。我将一些代码放入 GAC 中的 dll 中,现在我对 GAC 如何真正与 IIS 一起工作感到困惑。

在我们的 Intranet 环境中,我有几个相关的 Web 应用程序(大约 10 个)。每个应用程序都从一个单独的 url 运行,并且可能在其自己的应用程序池中运行。目前所有应用程序都在同一台服务器上,但这不是必需的。这种设置允许我们分别控制、开发和迁移每个应用程序。但是,我们希望每个应用程序的几个部分在我们的所有应用程序中都通用(母版页、登录页、菜单等)。管理层的要求是对这些文件的更改可以是通用的,并且无需必须重新编译和重新迁移每个 Web 应用程序。有很多方法可以完成这项任务,尽管有警告要避免使用 GAC,但这似乎确实是使用虚拟路径提供程序和存储在 GAC 中的 dll 有意义的情况。

我将一个虚拟路径提供程序放在一起,然后将我需要通用的文件和资源嵌入到一个 dll 中。(我本可以让 VPP 从数据库中提取文件,但我希望将文件嵌入 dll 本身会更高效。

并发症 #1

我不希望每个应用程序的开发人员都必须弄乱他们自己的 GAC 来测试和运行他们的应用程序,所以在每个解决方案中我只包含 Virtual Path Provider 项目,并将其结果 dll 复制到本地,(以及如强命名),这意味着提供程序 dll 及其嵌入文件被复制到应用程序的 bin 目录中。只要开发人员在他们的 GAC 中没有这个 dll 的版本(他们不应该),就会使用本地 bin 副本。这允许开发人员轻松更改和测试应用程序的文件和每个应用程序共有的文件。这也意味着除非故意阻止,否则通用 dll 也将存在于生产中的每个应用程序的 bin 目录中。但是,由于 IIS 将始终使用 GAC 版本(如果存在),

我现在认为这是合理的,因为在将应用程序复制到服务器时,我找不到一种简单的方法来同时将 VPP.dll 复制到本地进行开发,但又不复制到 bin 目录。

并发症 #2

实际上对应用程序进行编码以便它始终使用最新版本的 dll 而不是编译它的特定版本似乎是一件相当复杂的事情。(我还没有看到一个很好的例子来说明如何做到这一点,但我认为我需要一系列发布者政策)尝试更明显的答案似乎更容易——在迁移新的 dll 时保持 dll 的版本号不变版本的 VPP dll 到 GAC。这似乎工作正常,直到它没有。

使用服务器上的 Windows /assembly 管理单元,我将 GAC 中我的 dll 的旧版本 v. 1.0.0.0 替换为 v. 1.0.0.0 的更新副本。尽管我在 GAC 中更新了 dll,但我的应用程序继续使用旧版本的代码。重新启动 IIS,甚至完全重新启动服务器似乎都没有帮助。真正让我大吃一惊的是,最终 IIS 会神秘而出人意料地自我纠正,并开始使用来自 GAC 的 dll 的正确副本。

我见过许多这类与 GAC 相关的问题,这些问题似乎都以“突然我的网站又开始正常工作”结束了。我花了一段时间才发现这是 IIS 如何缓存我的强命名 dll 的结果,并且我误用了强命名 dll 应该工作的方式。

接下来,我尝试完全从 GAC 中删除 dll 的版本。因为在 bin 目录中仍然有我的 dll 的副本,所以我预计该过程要么失败,要么恢复/前进到 bin 目录中的版本。但是因为bin中的版本也是1.0.0.0,IIS继续使用dll的缓存副本,现在机器上已经不存在了。(这让我真的困惑了一段时间,因为我对GAC失去了信心版本一直在运行)

最后,我必须确保更新 dll 的唯一方法是从 GAC 中删除 dll 的副本,从 bin 目录中删除 dll 的副本,运行该站点以使其失败,然后将新的将 dll 版本导入 GAC。在此期间启动和停止 IIS 无效。这始终让我的应用程序使用新代码,但是……</p>

如此简单地将新版本的 dll 插入 GAC 并使其新效果无缝传播。

在阅读了一些相关问题之后,我现在正在尝试的是:

  1. 停止 IIS
  2. 更新 GAC 中 dll 的软件(但仍将新 dll 的版本号保留为 1.0.0.0 )
  3. 删除 'C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files' 文件夹中的所有内容(我认为这会强制重新编译,但这是一个修复的大锤)
  4. 重新启动 IIS。

这似乎是有效的,但似乎不得不去解决所有这些麻烦似乎有什么问题。有没有更简单的方法来强制 IIS 使用 GAC dll 的当前实例?有没有更好的方法来实现我所追求的效果。(一些通用文件 .aspx 和 .xml 文件在各种应用程序之间共享,可以与应用程序本身分开更新。)

编辑:根据 shahkalpesh 的评论,我在 microsoft
http://msdn.microsoft.com/en-us/library/7wd6ex19(VS.80).aspx找到了这个页面

它包括这个小知识:

重定向程序集版本 要将一个版本重定向到另一个版本,请使用该<bindingRedirect>元素。oldVersion 属性可以指定单个版本或一系列版本。例如,<bindingRedirect oldVersion="1.1.0.0-1.2.0.0" newVersion="2.0.0.0"/>指定运行时应使用版本 2.0.0.0 而不是 1.1.0.0 和 1.2.0.0 之间的程序集版本。

这意味着与我的 dll 一起,我可以推送一个将所有内容重定向到最新的发布者策略文件。那种缓解了我认为会是噩梦般的政策链的情况,我必须维护从每个可能版本到最新版本的链接......

我会试试这个,看看更新这样的版本是否也会触发 IIS 使用新文件的正确版本(在重置应用程序池之后)

4

3 回答 3

2

查看您的问题,您似乎希望在部署时使用更高版本的程序集。

在这种情况下,这个http://msdn.microsoft.com/en-us/library/eftw1fys(VS.71).aspx可能会有所帮助。

于 2009-04-19T22:23:10.403 回答
0

请记住,程序集版本和文件版本是不同的......它们可能会尝试将它们作为全新版本读取并引用它(而不是 1.0.0.0)。

于 2009-04-19T22:27:37.880 回答
0

为了让您放心 - 多年来,我们一直在用我们的共享程序集做非常相似的事情。

使用 GAC 时要记住的事项:

  1. 如果您要用相同的版本号替换现有版本的 DLL - 您必须首先删除以前的版本(从 c:\windows\assembly 删除,或者GACUtil /u) - 只需重新部署它/ GACUtil/etc 不会有任何影响 - 它认为 DLL 已经存在并且不更新它。
  2. 请记住 1,增加版本号会更容易,并且正如您所发现的,在配置链中的某处添加 BindingRedirect,通常我们使用 Machine.Config,因为我们希望影响服务器上的所有应用程序。
于 2009-09-22T19:53:25.393 回答