ASP.NET 调试时无法F11进行下一步调试同项目类库,并且调用类库方法报错:找不到方法

问题描述

今天在开发项目时,发现代码在调用某个方法的时候报错,报错内容很奇怪,从来没见过

找不到方法:System.String DHIS.BPM.Common.K2APITool.K2APIHelper.GetK2ProcessInstanceInfo(System.String, Int32)

上面是报错信息,根据报错信息猜测可能是因为没找到这个方法导致的,但是奇怪的点就在这里,明明代码是不报错的,并且项目编译通过没报错,F12也是可以转到代码的实现的,说明代码应该是没问题的。那么就调试一下看看是什么原因。

下面是代码背景介绍:
项目有两个:

  1. BPM (ASP.NET项目)
  2. Common (类库项目)

在BPM项目中,调用了Common项目的方法

方法调用逻辑示意:
BPM.InitializeWebContext -> Common.GetProcessInstance -> Common.GetK2ProcessInstanceInfo

InitializeWebContext方法:
在这里插入图片描述
GetProcessInstance:
在这里插入图片描述
GetK2ProcessInstanceInfo:
在这里插入图片描述

解决问题

从上面代码和调用逻辑来看,是很简单的方法调用,并且在ide中,代码是可以互相跳转的,并且检查了BPM项目的引用,发现Common的引用也是正常的
在这里插入图片描述

但是很奇怪的点出现了,在调试的过程中,突然发现在InitializeWebContext方法调用GetProcessInstance方法时,无法F11进入方法内部,并且直接进入InitializeWebContext方法的catch,报错内容就是最开头的报错。

这里就很奇怪了,明明项目引用是正确的,并且代码可以F12跳转过去,但是就是无法调试,并且报错找不到方法。
无法调试可能是PDB文件没有生成的原因,检查编译配置:发现编译配置是Debug模式,是正确的

简单来说,debug模式会生成pdb文件并且不会进行代码优化,方便调试
release模式一般不会生成或者生成的pdb文件不会包含完整的信息,减少文件输出大小,并且会优化代码
debug适合本地开发调试,release更适合生产

检查一下Common项目的bin目录,看看有没有pdb文件
在这里插入图片描述

发现dll文件和pdb文件都是最新生成的,并且都存在。
这时又怀疑是文件缓存之类导致的,又开始清理解决方案,重新生成,测试,但是发现没用,仍然是那个报错。

这个时候通过搜索问题和询问GPT,发现可能是dll文件版本不对导致的,准备对比一下Common项目bin目录下的dll文件和BPM项目引用的dll文件版本是否一致。结果发现又是一样的…
此时还是怀疑引用的dll文件不是最新的,所以使用了ILSpy和VS的对象浏览器功能,反编译查看方法是否存在
ILSpy反编译
对象浏览器
麻了,反编译发现dll文件是对的。

这时已经毫无头绪不知道怎么继续排查了,所以只能继续询问GPT,看看有没有头绪
在这里插入图片描述

GPT回答:
PDB文件丢失或不匹配:
- 调试信息(PDB文件)缺失或与DLL不匹配,会导致无法进入类库代码进行调试。确保在生成解决方案时包含了PDB文件,并且部署到正确的路径。
代码优化:
- 在发布配置中,代码优化会使得调试器难以正确映射源代码。尝试在Debug配置下运行项目,确保优化被关闭。
版本不一致:
- 确保引用的DLL版本与本地调试的代码版本一致。有时项目中引用了旧版本的DLL而不是最新编译的版本,会导致运行时找不到方法。
符号加载问题:
- 检查Visual Studio中是否正确加载了符号。可以在“调试 -> 符号”中手动加载符号文件。
程序集引用路径错误:
- 确保项目中引用的DLL路径正确,尤其是在多项目解决方案中,可能会因为路径配置问题引用到错误的DLL。
强名称冲突:
- 如果类库使用了强名称签名,确保项目引用的DLL和调试时加载的DLL签名一致。

GPT回答了几个方向,目前怀疑是dll的签名不一致,所以继续询问
在这里插入图片描述
此时,关键来了,GPT的回答中,说到了一个关键点:可以在 调试->窗口->模块 中,查看引用的dll文件具体的地址以及pdb信息
这个时候按照步骤查看引用的dll信息,突然发现,Common项目的路径和其他dll不一样!!!
在这里插入图片描述

上图有些问题,因为截图的时候bug已经解决了,所以和描述有点不一样,不过可以看图中最后一个,最后一个的路径和其他也是不一样的

正常的dll引用地址都是:C:\Users\wbguo.yu\AppData\Local\Temp\Temporary ASP.NET Files\vs\a27930e3\b1b0b19d\assembly\dl3
但是Common项目的引用地址却是:C:\Windows\assembly\GAC_MSIL\DHIS.BPM.Common\1.0.0.0__9af3289ac427fbfa
而且可以通过图中发现,不正常的dll文件,符号状态是未加载的,这也是为什么无法调试的原因

于是再次询问GPT
在这里插入图片描述
这次GPT直接回答了问题的关键点,GAC全局程序集缓存

关于GAC全局程序集缓存,简单来说就是:GAC(Global Assembly Cache,全局程序集缓存)是 .NET Framework 提供的一种用于存储全局共享程序集的特殊文件夹。优点:共享程序集,版本控制,强命名,减少冗余。

在这里插入图片描述

根据提示,先查询gac中是否包含Common的dll

注意:在执行gacutil命令时,需要打开VS的命令行窗口(Developer Command Prompt for VS 2019),如果是执行删除命令,需要用管理员权限打开

gacutil -l | find "DHIS.BPM.Common"

这里就不放图了,因为写文章的时候问题已经解决了

发现Common确实存在GAC中,这下算是找到原因了,因为GAC中有这个dll文件,所以每次调试都来这里获取了,并且每次dll修改,并没有同步到GAC中,所以无法调试,获取不到最新的方法

解决方案:直接执行删除命令,删除GAC中的Common项目的dll

gacutil -u DHIS.BPM.Common

删除后,再次去VS中进行调试,并且观察 调试->窗口->模块 页面,此时发现Common的dll文件地址已经正确,在测试功能,发现可以正常调试,并且也不会报错找不到方法了。

至此,问题重要算是解决了。

问题总结

这个问题真的是很妖怪,刚开始解决时根本不知道如何下手,后来通过GPT给出的方向逐一排查最终定位到问题。不过通过这个问题可以学习到两个新知识:

  1. GAC 全局程序集缓存
  2. VS的 调试->窗口->模块 可以查看当前调试时引用的dll路径

至于为什么项目中的dll文件会被加入到GAC中,这个我也不清楚了- -,因为新入职用的是别人之前的电脑,环境都是安装好的,可能是上个人不小心误操作了吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值