VB程序老崩溃?这套错误处理机制让我三年没出过事故
VB程序老崩溃这套错误处理机制让我三年没出过事故写VB的人分两种一种是程序报错了才知道哪里出问题另一种是程序还没崩就已经把异常兜住了。我以前属于第一种做的库存管理系统上线第一天就崩了三次客户打电话过来骂人。后来我花了整整两个月研究VB的错误处理机制才真正明白会写代码不算本事会处理错误才算。今天这篇把我这些年总结的异常处理方案全部摊开直接能抄进项目里。一、为什么VB的错误处理这么重要☆ 1、VB是弱类型语言运行时错误特别多。类型不匹配、下标越界、除以零、空对象引用这些错误在编译期根本发现不了只有运行时才会暴露。☆ 2、企业管理系统不是你自己用的是给文化程度参差不齐的一线员工用的。他们会在必填框里填空格会在数字框里输入字母会在你没想到的地方给你制造异常。☆ 3、没有错误处理的VB程序崩起来连个提示都没有直接闪退。用户不知道发生了什么只会觉得你的软件是垃圾。我之前给一个物流公司写调度系统因为没做错误处理有一次数据库连接断开程序直接白屏退出调度员正在排单数据全丢了。从那以后我每个程序的第一件事就是写错误处理框架。二、VB错误处理的三种方式☆ 1、On Error Resume Next最常用也最危险这句话的意思是出错了别停继续往下执行。它适合用在你明确知道某个操作可能失败、而且失败了也不影响主流程的场景。vbOn Error Resume NextDim rs As ADODB.RecordsetSet rs conn.Execute(SELECT * FROM 员工表)If Err.Number 0 ThenMsgBox 查询失败 Err.Description, vbCriticalErr.ClearExit SubEnd IfOn Error GoTo 0 关掉错误忽略恢复正常报错☆ 2、On Error GoTo 标签最规范这是我最推荐的方式。出错后跳到指定的错误处理代码块统一处理处理完可以选择Resume回到出错的地方继续执行也可以选择Exit退出。vbPrivate Sub btnSave_Click()On Error GoTo ErrHandlerDim sql As Stringsql UPDATE 员工表 SET 姓名 txtName.Text WHERE 工号 txtID.Text modDB.ExecuteSQL sqlMsgBox 保存成功, vbInformationExit SubErrHandler:MsgBox 操作失败 Err.Description, vbCriticalErr.ClearEnd Sub☆ 3、不写任何错误处理最傻这种写法在VB6里也能跑但一旦出错程序直接崩溃用户体验为零。如果你的程序只有自己用那随便。如果是给别人用的千万别这么干。三、实战搭一套通用的错误处理框架我在每个项目里都会建一个modError.bas模块把所有错误处理的公共逻辑放进去主窗体直接调用。☆ 1、封装一个全局错误处理过程vb modError.bas Option ExplicitPublic Sub SafeExecute(procName As String, proc As Object)On Error GoTo ErrHandlerApplication.MousePointer vbHourglass 鼠标变沙漏Call procApplication.MousePointer vbDefault 鼠标恢复Exit SubErrHandler:Application.MousePointer vbDefaultDim errMsg As StringerrMsg 【 procName 】执行出错 vbCrLferrMsg errMsg 错误号 Err.Number vbCrLferrMsg errMsg 错误描述 Err.Description vbCrLferrMsg errMsg 发生位置 Err.Source写入日志文件WriteLog errMsg弹窗提示用户MsgBox errMsg, vbCritical, 系统错误Err.ClearEnd SubPrivate Sub WriteLog(msg As String)Dim fileNum As IntegerfileNum FreeFileDim logPath As StringlogPath App.Path \error.logOpen logPath For Append As #fileNumPrint #fileNum, Now | msgClose #fileNumEnd Sub☆ 2、在主窗体中调用vbPrivate Sub btnSearch_Click()SafeExecute btnSearch_Click, AddressOf DoSearchEnd SubPrivate Sub DoSearch()Dim sql As Stringsql SELECT * FROM 员工表 WHERE 姓名 LIKE % txtSearch.Text %Dim rs As ADODB.RecordsetSet rs modDB.GetRecordset(sql)Set dgvList.DataSource rsEnd Sub这样写的好处是不管哪个按钮出了错都会自动记录日志、弹窗提示、鼠标恢复用户体验一致排查问题也方便。四、五种最常见的运行时错误及处理方案☆ 1、错误号3021没有找到记录BOF或EOF为True这个错误在记录集为空时特别常见。很多人直接用On Error Resume Next忽略掉结果后面的代码全在空对象上跑越错越离谱。vbDim rs As ADODB.RecordsetSet rs modDB.GetRecordset(SELECT * FROM 员工表 WHERE 工号99999)If rs Is Nothing ThenMsgBox 查询失败请检查数据库连接。, vbExclamationExit SubEnd IfIf rs.EOF ThenMsgBox 没有找到该员工记录。, vbInformationrs.CloseSet rs NothingExit SubEnd If正常处理数据rs.MoveFirstDo While Not rs.EOFDebug.Print rs!姓名rs.MoveNextLooprs.CloseSet rs Nothing☆ 2、错误号91对象变量未设置Nothing这个错误说明你在用一个没初始化的对象。最常见的场景是Recordset用完没关下次再打开时连接已经断了。vb错误写法Dim rs As ADODB.RecordsetSet rs conn.Execute(sql) 如果conn是Nothing这里直接报错91正确写法On Error GoTo ErrHandlerIf conn Is Nothing ThenInitDB 重新初始化连接End IfSet rs conn.Execute(sql)☆ 3、错误号13类型不匹配这个错误通常发生在把文本框的内容直接拼进SQL语句时。用户输入了非数字内容拼接后类型对不上。vb错误写法Dim age As Integerage txtAge.Text 如果用户输入了abc直接报错13正确写法On Error Resume NextDim age As Integerage CInt(txtAge.Text)If Err.Number 13 ThenMsgBox 年龄必须是数字, vbExclamationtxtAge.SetFocustxtAge.SelStart 0txtAge.SelLength Len(txtAge.Text)Err.ClearExit SubEnd IfOn Error GoTo 0☆ 4、错误号5无效的过程调用这个错误通常发生在调用了一个不存在的方法或者参数传错了。vb错误写法rs.MoveNext 如果rs已经被关闭了这行就报错5正确写法On Error Resume Nextrs.MoveNextIf Err.Number 5 ThenDebug.Print 记录集已关闭Err.ClearExit DoEnd IfOn Error GoTo 0☆ 5、错误号-2147217900SQL语法错误这个错误说明你拼的SQL语句有问题最常见的原因是用户输入里包含单引号。vb错误写法sql SELECT * FROM 员工表 WHERE 姓名 txtName.Text 如果txtName.Text是 OBrienSQL就变成了 WHERE 姓名OBrien单引号不配对直接报错正确写法写一个单引号过滤函数Private Function EscapeSQL(input As String) As StringEscapeSQL Replace(input, , )End Functionsql SELECT * FROM 员工表 WHERE 姓名 EscapeSQL(txtName.Text) 五、错误处理的五条实战原则☆ 1、能预防的错误别靠捕获。用户在年龄框里输入字母你就该用KeyPress事件限制只能输入数字而不是等出错了再弹个框。☆ 2、关键操作一定要加错误处理。数据库的增删改、文件的读写、网络请求这三样只要涉及外部资源就必须加On Error。☆ 3、错误处理里一定要写日志。弹窗用户看完就关了但日志能帮你三天后找到问题根源。我的习惯是每个错误都记录时间、错误号、错误描述、出错位置。☆ 4、Err.Clear要及时调用。错误处理完不Clear后面的代码会继续沿用旧的Err对象导致误判。☆ 5、On Error GoTo 0要及时恢复。开了错误跳转就一直跳转关掉才能让后面的错误正常暴露出来。六、新手最常犯的三个错误处理误区☆ 1、On Error Resume Next写完就忘了关。这个语句是全局生效的你在A过程里开了B过程里也会继续忽略错误直到你写On Error GoTo 0才恢复。我见过有人整个模块都在静默失败查了一天才发现是Resume Next没关。☆ 2、错误处理里只写MsgBox不写恢复逻辑。弹个框告诉用户出错了然后呢程序卡在那里用户什么都干不了。正确做法是弹完框后要么Exit Sub退出当前过程要么Resume回到出错位置重试。☆ 3、所有错误都用同一种方式处理。运行时错误和逻辑错误应该分开处理。运行时错误数据库断开、文件不存在需要记录日志逻辑错误用户输入不合法需要提示用户重新输入。混在一起处理排查问题会非常痛苦。七、写在最后VB这门语言写功能不难难的是写稳定。我做了这么多年VB开发最大的感受就是代码写得再漂亮一崩全白搭。错误处理不是锦上添花是基本功。你的程序能不能在客户那里稳定跑三个月不出事全看这套机制做得扎不扎实。上面这套框架和处理方案是我在二十多个项目里反复打磨出来的不是教科书上的理论是真正跑过生产环境的东西。拿去直接用改改日志路径和错误提示语就行。注意本文所介绍的软件及功能均基于公开信息整理仅供用户参考。在使用任何软件时请务必遵守相关法律法规及软件使用协议。同时本文不涉及任何商业推广或引流行为仅为用户提供一个了解和使用该工具的渠道。你在生活中时遇到了哪些问题你是如何解决的欢迎在评论区分享你的经验和心得希望这篇文章能够满足您的需求如果您有任何修改意见或需要进一步的帮助请随时告诉我感谢各位支持可以关注我的个人主页找到你所需要的宝贝。博文入口山峰哥-CSDN博客 复制到【浏览器】打开即可,宝贝入口夸克网盘分享 宝贝夸克网盘分享作者郑重声明本文内容为本人原创文章纯净无利益纠葛如有不妥之处请及时联系修改或删除。诚邀各位读者秉持理性态度交流共筑和谐讨论氛围 复制整篇文章