c# 代码调试技巧和如何远程调试
作者:一线码农 发布时间:2022-09-26 14:11:19
一:背景
1. 讲故事
每次项目预交付的时候,总会遇到各种奇葩的坑,我觉得有必要梳理一下以及如何快速解决的,让后来人避避坑,这篇就聊聊自己的所闻所遇:
我去,本地环境代码跑的哧溜,上了测试环境出问题
我去, 第三方提供的 dll 跑出 bug 了
二:两个大坑的解决方案
1. 本地环境没问题,上了测试出问题
相信很多朋友都有我这样类似的遭遇,明明程序代码,配置文件都一样,挪了一个窝就出问题,你说气人不,既然问题出了那怎么快速解决呢? 对,就是用调试,但程序部署在 centos 上,送一个 visualstudio 上去也不现实,在这种限制级条件下还想调试怎么办呢?不错,可以上远程调试,然后就很快查到了测试机器中的某一个环境变量搞错了,事情的来龙去脉搞清楚了,接下来就看看怎么实现 local 到 centos 的 远程调试。
1) 测试代码
为了方便演示,我就在 Action 中读取 strategy 环境变量。
public class HomeController : Controller
{
public IActionResult Index()
{
ViewBag.strategy = Environment.GetEnvironmentVariable("strategy");
return View();
}
}
2) 安装 SSH
要远程调试,需要在远端机安装 SSH,因为后面附加进程调试 就要借助 SSH 打通。
yum install openssh-server unzip curl
安装完成后,就能看到 22 端口已启动
[root@localhost data]# netstat -tlnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1126/sshd
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 3037/cupsd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1739/master
tcp6 0 0 :::22 :::* LISTEN 1126/sshd
tcp6 0 0 ::1:631 :::* LISTEN 3037/cupsd
tcp6 0 0 ::1:25 :::* LISTEN 1739/master
3) 程序的发布配置
发布配置上,第一个要确保是 debug 版本,第二个要确保是 可移植模式 (Portable), 如下图:
4) 使用附加进程调试
在菜单栏依次选择:Debug -> Attach To Process,然后填写 ssh 需要的各种信息,如下图:
点击 Connect 后,就能看到远端机器的 dotnet程序 进程号,选择该进程进行附加,在 Select Code Type 中选择 Nanaged (.NET Core for Unix)即可,如下图:
5) 顺利调试
在 浏览器中键入: http://192.168.142.130/Home/Index ,可以看到我的 C# 代码被命中,也顺利的拿到了远端机器的 环境变量,问题也就迎刃而解。
2. 第三方 dll 出 bug 了
调试程序除了使用 F9 进行调试,相信也有不少朋友知道断点是可以编辑的,比如说:设置表达式断点,过滤器断点,命中次数断点,动作断点,下如图:
第一个问题就来了,这些花式断点,你真的会用吗?真的会经常用吗?
让我来回答的话,不到万不得已我是不会用的,我更愿意在代码中加入利于调试的测试语句,原因有三点:
更加灵活
这个显而易见,在面板中设置条件相比用纯语句设置要麻烦得多,点来点去,而且还要条件叠加,复杂的很,我是不喜欢。
功能强大
编辑面板上只有简单的并且关系,而且各个条件还是同级别的,无法做到各个条件的或者关系以及层级或者递归的包含关系,所以。。。没办法。。。
更易于保存
这个就有意思了,在断点上右键是弹出编辑面板,点击左键是关闭断点,问题就出在这里,经常由于手贱,本想点右键结果点了左键 😨😨😨。。。。 好不容易设置好的条件没了。。。真的没了😭😭😭,从此以后,路转黑。如下图:
那这么说断点编辑真的没用吗? 我觉得只有在不能修改语句的调试场景下能够大显身手,比如我遇到的调试厂家封装的dll,哈哈,既然说到了断点,我就用 dnspy 演示几个断点给大家复习一下吧!
1) 测试代码
为方便演示,用 for 循环案例是最好的。
public static void Main(string[] args)
{
var sum = 0;
for (int i = 0; i < 10000; i++)
{
sum += i;
}
Console.WriteLine($"sum={sum}");
}
2) 我希望在 sum = 1035 的时候命中断点
这个用条件表达式断点就可以了,非常简单,如下所示:
3) 找到所有能够被 1800 整除的数,并且记录下当时的 i 和 sum 值
这里就可以用到 Action 断点的日志记录,在 for 循环迭代中,不需要中断断点,只需记录某一个特定状态下当前的 i 和 sum 的值,对调试代码非常有帮助,如下图:
三:总结
总的来说这两个经验也算我一步一步踩坑过来的,如果能帮到你就更好了,本篇就聊这么多,下篇再见!
来源:https://www.cnblogs.com/huangxincheng/archive/2020/11/04/13924326.html


猜你喜欢
- 问题描述:输入:两个日期输出:两个日期相差的天数具体代码实现方法1:通过Calendar类的日期比较。注意:这里需要考虑一下:日期是跨年份的
- 本文实例为大家分享了java实现鲜花销售系统的具体代码,供大家参考,具体内容如下一、练习目标1.体会数组的作用2.找到分层开发的感觉3.收获
- CyclicBarrier 接着讲多线程下的其他组件,第一个要讲的就
- 正常状态是UP,跳闸是⼀种状态CIRCUIT_OPEN,可以通过/health查看,前提是工程中需要引入SpringBoot的actuato
- 1、首先 当然是启动genymotion2、然后Tomcat ,启动tomcat。。如图将请求的URL地址变为10.0.3.2 ,比如在电脑
- java 在Jetty9中使用HttpSessionListener和FilterHttpSessionListener当Session创建
- 前言之前介绍了 Animatable 动画以及其 animateTo和 snapTo两个开启动画 api 的使用,实际上 Animatabl
- java和javascript长得是如此地相像,那么它们是一回事儿吗?现在让我来揭晓答案吧!JavaScript 是一种嵌入式脚本文件,直接
- 1.问题引出源码: public static void main(String[] args) { List&l
- 泛型概述我们都知道集合中是可以存放任意对象的,只要把对象存储集合后,那么这时他们都会被提升成Object类型。当我们在取出每一个对象,并且进
- 安卓项目开发中,项目中使用到jni开发,使用C/C++编写了自己的so库,调试和运行一切正常,Android.mk文件代码如下:LOCAL_
- 这篇文章主要介绍了Java使用Collections工具类对List集合进行排序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一
- 1. 面试第一步,自我介绍。这个自我介绍,在整个面试当中可以说是第一步,如果你能把你想说的重点说出来,把面试官带到你准备好的技术点中,可以说
- 本文实例讲解了Android实现图片文字轮播特效的详细代码,分享给大家供大家参考,具体内容如下图片轮播是类似知乎日报上的一个轮播效果,如下图
- Shiro介绍Shiro是一款安全框架,主要的三个类Subject、SecurityManager、RealmSubject:表示当前用户S
- 首先声明一点,这里的重试并不是报错以后的重试,而是负载均衡客户端发现远程请求实例不可到达后,去重试其他实例。@Bean@LoadBalanc
- 一、项目简述功能包括(管理员和学生角色): 管理员和学生登录,图书管理,图书添加删除修改,图书 借阅,图书归还,图书查看,学生管理,借还管理
- C++11 引入一个全新的线程库,包含启动和管理线程的工具,提供了同步(互斥、锁和原子变量)的方法,我将试图为你介绍这个全新的线
- Unsafe类是啥?Java最初被设计为一种安全的受控环境。尽管如此,Java HotSpot还是包含了一个“后门”,提供了一些可以直接操控
- 本文实例讲述了Android实现Service获取当前位置(GPS+基站)的方法。分享给大家供大家参考。具体如下:需求详情:1)、Servi