8

更新:昨晚,我认为更改保存某些报告的文件夹的工作量太大。我的解决方法是重命名文件夹,运行我需要完成的批处理作业,然后将文件夹名称改回原来的名称。我觉得我可以把今天剩下的时间和下周的所有时间都花在这上面,但仍然没有什么可展示的。我宁愿因为与我的老板背道而驰,也不愿不能向我们的客户开具发票(这种情况每年只发生一次)。感谢所有帮助过的人,我为你愿意帮助一些匿名的家伙而感到谦卑。我不知道如何“放弃”这个问题,但仍然给你们提供道具,我会在午餐时阅读常见问题解答和任何评论。谢谢你。

我正在尝试调试我的前任创建的 ac# 应用程序。他是程序员,我是系统管理员,也许这就是我出错的地方。

无论如何,我需要重新编译其中一个程序集并将其部署到我们的生产服务器。当我编译它时,我得到了错误:

'Mcrcsip.Web.McrcsipWebExceptionBase 类型在未引用的程序集中定义。您必须添加对程序集“Mcrcsip.Web, Version=2.0.3266.28977, Culture=neutral, PublicKeyToken=c3de6c6abcdf794b”的引用。

我碰巧有该程序集的副本,当我删除对现有程序集的引用(具有不同公钥令牌的 2.0.0.0)并添加对它所要求的程序集的引用时,当我编译时,出现此错误信息:

'Mcrcsip.Web.McrcsipWebExceptionBase 类型在未引用的程序集中定义。您必须添加对程序集“Mcrcsip.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=8bbdde85caf008d0”的引用。

如果我在谷歌上搜索这个错误(当然是通用的),我会得到一堆“这就是你添加程序集引用的方式......”结果。

我该如何摆脱这个旋转木马?

以下是解决方案的布局方式:

  • Mcrcsip.Amwa.Solution
    • http://amwa-test.internal.lan/
    • Mcrcsip.Amwa.Core
      • Mcrcsip.Aws.Bol
      • Mcrcsip.Common
      • Mcrcsip.Web
      • nunit.framework
      • 系统
      • 系统配置
      • 系统数据
      • 系统.企业服务
      • 系统.Web
      • 系统.Web.服务
      • 系统.XML
    • Mcrcsip.Amwa.CrFactory
      • CrystalDecisions.CrystalReports.Engine
      • CrystalDecisions.Enterprise.Framework
      • CrystalDecisions.Enterprise.InfoStore
      • CrystalDecisions.ReportSource
      • CrystalDecisions.Shared
      • CrystalDecisions.Web
      • Mcrcsip.Amwa.Core
      • Mcrcsip.Web
      • 系统
      • 系统配置
      • 系统数据
      • 系统绘图
      • 系统.Web
      • 系统.XML
    • Mcrcsip.Amwa.PdfFormHandler
      • itextsharp
      • Mcrcsip.Amwa.Core
      • Mcrcsip.Web
      • 系统
      • 系统配置
      • 系统数据
      • 系统.Web
      • 系统文件
    • Mcrcsip.Amwa.Web
      • Mcrcsip.Amwa.Core
      • Mcrcsip.Amwa.CrFactory
      • Mcrcsip.Amwa.PdfFormHandler
      • Mcrcsip.Aws.BOL
      • Mcrcsip.Common
      • Mcrcsip.SharePoint
      • Mcrcsip.Web
      • 系统
      • 系统配置
      • 系统数据
      • System.EnterpriseServices
      • 系统.Web
      • 系统.Web.服务
      • 系统.XML
    • Mcrcsip.Amwa.WebControls
      • 系统
      • 系统数据
      • 系统设计
      • 系统绘图
      • 系统.Web
      • 系统文件
    • Mcrcsip.Amwa.Setup
4

3 回答 3

7

参考不一致或:我如何学会如何停止担心并爱上 ILDASM

咳咳咳,

问题

缺口,

通过重新阅读您的原始帖子,很明显您有一个 dll 版本不一致的问题。也就是说,您的解决方案中至少有一个项目依赖于 Mcrcsip.Web 版本 X,并且您的解决方案中至少有一个项目依赖于 Mcrcsip.Web 版本 Y [或者更糟糕的是,依赖于依赖于 Mcrcsip.Web 版本 Y 的库]。追踪这些可能既困难又乏味。

请参阅推荐的解决方案以跳到最后。

如何

当出现这种不一致时

  1. 您有一个依赖项,例如 A 依赖于 B 和 C,B 依赖于 C,
  2. A 和 B 最初是针对 C 版本 1 构建的,
  3. A 是针对 C 版本 2 更新和构建的,

与我们的直觉预期相反,当我们构建 A 时,B 不会自动更新为使用 C 版本 2。A 和 B必须引用同一个库才能正确构建。所以要么 A 必须符合 C ver 1,要么 B 必须重建并符合 C ver 2。

现在,这可能发生在任何项目配置中,这就是为什么对您的软件进行版本控制很重要的原因[相信我,如果没有正确的签名\版本控制,这个问题会变得更糟],并且每当发生依赖项更新时,在您的团队中进行良好的沟通。

还值得知道有两种依赖引用,硬的和软的[其实它们是一样的,就是链接到dll,除了一种是另一种的特例,从概念上有助于区分这两种]。

硬引用

硬引用是项目对静态 dll 的依赖。也就是说,依赖项是在特定时间构建的,除非将其物理文件替换为新文件,否则将永远不会更新。硬引用通过添加引用对话框添加到解决方案,并从 .Net、COM 或浏览选项卡添加引用。硬引用通常用于添加对在当前解决方案范围之外开发的软件的依赖项[即框架、第三方和其他内部团队开发的其他第一方产品]。硬引用也有变得陈旧的趋势,因为它们是由自己的开发流维护和更新的。

假设上面的场景

  1. 您有一个依赖项,例如 A 依赖于 B 和 C,B 依赖于 C,
  2. A 和 B 最初是针对 C 版本 1 构建的,
  3. A 是针对 C 版本 2 更新和构建的,

此外,假设 A 和 B 在同一解决方案中

  • 简单解决方案
    • 一个
      • B [硬参考]
      • C v2 [硬参考]
      • C v1 [硬参考]

构建 A 后,您将收到您描述的错误。A 期望来自 C v2 的对象,但由于 B 对 C v1 有硬依赖,因此 C v1 会先加载到内存中,并发生冲突。A 期望 v2 并找到 v1。那是你的错误。

要解决这种情况,您必须

  1. 将项目 B 硬引用 C v1 更新为 C v2
  2. 强制重建项目 B
  3. 将项目 A 硬引用 B 更新为 [新建] B
  4. 强制重建 A

软引用

软引用是一个项目对同一解决方案中另一个项目的依赖关系。也就是说,每次重建整个解决方案时都会重建依赖关系。软引用通过“添加引用”对话框添加到解决方案,并从“项目”选项卡添加引用。软引用通常用于向在当前解决方案范围内开发的软件添加依赖项,它们的主要优点是在同一解决方案中对消费者进行更改时传播更改。由于这个事实,软引用不会过时。

[这是硬引用的一种特殊情况,Visual Studio 会添加一个指向目标项目的输出路径的引用,我相信如果目标项目更改其输出配置,它也会更新此路径——但这是一个非常方便的功能权证区分]

假设上面的场景

  1. 您有一个依赖项,例如 A 依赖于 B 和 C,B 依赖于 C,
  2. A 和 B 最初是针对 C 版本 1 构建的,
  3. A 是针对 C 版本 2 更新和构建的,

此外,假设 A 和 B 在同一解决方案中

  • 简单解决方案
    • 一个
      • B [软参考]
      • C v2 [硬参考]
      • C v1 [硬参考]

构建 A 后,您将收到您描述的错误。A 期望来自 C v2 的对象,但由于 B 对 C v1 有硬依赖,因此 C v1 会先加载到内存中,并发生冲突。A 期望 v2 并找到 v1。那是你的错误。

解决,

  1. 将项目 B 硬引用 C v1 更新为 C v2
  2. 强制重建 A

如您所见,软引用更易于维护。

IL DASM [中间语言 DisASeMbler]

既然您对引用和项目维护有了更多了解,那么您究竟如何确定构建的状态?毕竟,您的任何一个项目或其依赖项都可能不一致。

简单的方法是打开您的构建输出目录,并检查您的解决方案生成的每个 dll 的程序集清单。

要检查程序集的清单,

  1. 打开ildasm.exe
    • 对于 VS2010,ildasm 可从快捷方式获得
    • 对于 VS2008 和 VS2005,打开 Visual Studio 命令提示符,从命令行输入“ildasm”
  2. 打开一个dll,
    • 单击文件 -> 打开,或
    • 按 Ctrl-O,或
    • 将您的 dll 拖放到ildasm窗口中
  3. 打开清单
    • 双击标记为 MANIFEST 的红色三角形节点
  4. 查找对 Mcrcsip.Web 的引用
    • 单击查找并在对话框中输入 Mcrcsip.Web,或
    • 按 Alt-F 并在对话框中输入 Mcrcsip.Web,或
    • 手动检查 MANIFEST 文件的内容
  5. 验证版本号

这是乏味和痛苦的,但如果你遇到 [non-trivial] dll 不一致错误,这是找到它的唯一方法。

推荐解决方案

  1. 确保您的解决方案在适用的情况下使用软引用,
    • 展开 Mcrcsip.Amwa.CrFactory
      • 展开参考
      • 删除参考 Mcrcsip.Amwa.Core
      • 打开添加引用对话框
      • 从项目选项卡打开 Mcrcsip.Amwa.Core
    • 展开 Mcrcsip.Amwa.PdfFormHandler
      • 展开参考
      • 删除参考 Mcrcsip.Amwa.Core
      • 打开添加引用对话框
      • 从项目选项卡打开 Mcrcsip.Amwa.Core
    • 展开 Mcrcsip.Amwa.Web
      • 展开参考
      • 删除参考 Mcrcsip.Amwa.Core
      • 删除参考 Mcrcsip.Amwa.CrFactory
      • 删除参考 Mcrcsip.Amwa.PdfFormHandler
      • 打开添加引用对话框
      • 从项目选项卡打开 Mcrcsip.Amwa.Core
      • 从项目选项卡打开 Mcrcsip.Amwa.CrFactory
      • 从项目选项卡打开 Mcrcsip.Amwa.PdfFormHandler
  2. 确保您的解决方案在适用的情况下使用新的硬引用,
    • 展开 Mcrcsip.Amwa.Core
      • 展开参考
      • 删除参考 Mcrcsip.Aws.Bol
      • 删除参考 Mcrcsip.Common
      • 删除参考 Mcrcsip.Web
      • 打开添加引用对话框
      • 从浏览选项卡中打开 Mcrcsip.Aws.Bol [始终最好指定位置]
      • 从浏览选项卡打开 Mcrcsip.Common
      • 从浏览选项卡打开 Mcrcsip.Web
    • 展开 Mcrcsip.Amwa.CrFactory
      • 展开参考
      • 删除参考 Mcrcsip.Web
      • 打开添加引用对话框
      • 从浏览选项卡打开 Mcrcsip.Web
    • 展开 Mcrcsip.Amwa.PdfFormHandler
      • 展开参考
      • 删除参考 Mcrcsip.Web
      • 打开添加引用对话框
      • 从浏览选项卡打开 Mcrcsip.Web
    • 展开 Mcrcsip.Amwa.Web
      • 展开参考
      • 删除参考 Mcrcsip.Aws.Bol
      • 删除参考 Mcrcsip.Common
      • 删除参考 Mcrcsip.SharePoint
      • 删除参考 Mcrcsip.Web
      • 打开添加引用对话框
      • 从浏览选项卡打开 Mcrcsip.Aws.Bol
      • 从浏览选项卡打开 Mcrcsip.Common
      • 从浏览选项卡打开 Mcrcsip.SharePoint
      • 从浏览选项卡打开 Mcrcsip.Web
  3. 建造

如果您在这一步仍然遇到错误,那么您知道其中一项或全部

  • Mcrcsip.Aws.BOL
  • Mcrcsip.Common
  • Mcrcsip.SharePoint

共享您对 Mcrcsip.Web 的依赖,并引用旧版本。如果是这种情况,那么对于上面列出的每个硬参考

  1. 选择参考
  2. 按 F4
  3. 从 Path 属性复制内容
  4. 打开文件对话框ildasm
  5. 粘贴到文件名
  6. 检查清单

确保对上述三个硬引用中的每一个都执行此操作。一旦您确定这三个子集的哪个子集引用了旧版本的 Mcrcsip.Web,您现在可能会找到该项目,更新硬引用,重新构建它,然后最后更新您的硬引用,重新构建,瞧。鲍勃是你的叔叔。

呸。

勒芬

PS 为冗长而道歉。这不是一个非常复杂的问题,但我相信你会同意,它涉及很多细节。我真的希望这会有所帮助。也感谢您的合作:)

PPS 顺便说一句,我从您的评论中推断出原始开发人员在任何地方都使用了硬引用[即即使在相同的解决方案中]。也许他有他的理由,但在我看来,那是屁股。

于 2010-03-04T19:13:34.927 回答
0

如果您右键单击引用,转到属性,“特定版本”设置为什么?确保它设置为“True”并且列出的版本确实是 2.0.x。

在属性页面中,仔细检查路径。您可能在 GAC 的其他地方注册了一个不同的版本,该版本获得了优先权。在命令行中使用“gacutil -l”来获取该程序集的所有注册版本的列表。如果您看到具有不同密钥的重复项,请使用 gacutil 核对您不想要的那个。

于 2010-03-04T19:17:39.497 回答
0

在“批量构建”选项下观看其他构建。这将让您优先考虑首先构建哪个程序集,然后依赖项将按照正确的顺序获取它们的 DLL。

于 2010-03-04T21:05:37.777 回答