vb 的小脚本解决大问题:基础篇——语法精讲、过程与函数、错误处理【WSH 运行、FSO、Err 对象、巡检脚本实战】

✍️ 作者:王文峰(外号:神秘小峯 / 山峯)|中国国学、传统文化与代码爱好者的程序人生,期待你的关注和支持!

vb的小脚本解决大问题:基础篇

    • 一、开篇:小脚本解决的大问题
    • 二、运行环境与第一个脚本
    • 三、语法精讲:变量、运算符、流程控制
      • [1. 变量与类型](#1. 变量与类型)
      • [2. 运算符(三个高频坑)](#2. 运算符(三个高频坑))
      • [3. 流程控制四件套](#3. 流程控制四件套)
      • [4. 常用内置函数(字符串为王)](#4. 常用内置函数(字符串为王))
      • [5. 数组:动态扩容](#5. 数组:动态扩容)
    • [四、过程与函数:Sub 与 Function 的分工](#四、过程与函数:Sub 与 Function 的分工)
      • [1. Sub vs Function(必考)](#1. Sub vs Function(必考))
      • [2. 参数默认 ByRef(VBScript 第一大坑)](#2. 参数默认 ByRef(VBScript 第一大坑))
      • [3. 退出与作用域](#3. 退出与作用域)
    • [五、错误处理:On Error Resume Next 是唯一武器](#五、错误处理:On Error Resume Next 是唯一武器)
      • [1. 标准姿势:出错 → 检查 → 清理](#1. 标准姿势:出错 → 检查 → 清理)
      • [2. 手动抛错:Err.Raise](#2. 手动抛错:Err.Raise)
      • [3. 两个必须知道的坑](#3. 两个必须知道的坑)
      • [4. 统一错误处理模板(推荐收藏)](#4. 统一错误处理模板(推荐收藏))
    • [六、实战:目录巡检 + 日志脚本](#六、实战:目录巡检 + 日志脚本)
    • 七、避坑清单(血泪总结)
    • 八、总结与自测清单
  • [🎯 学习教程(传送门)](#🎯 学习教程(传送门))
  • [🔥 往期文章](#🔥 往期文章)

📚 本文是「vb 的小脚本解决大问题」系列第一篇。机房里没有编译器、服务器不让装 Python、Excel 要批量处理------Windows 自带的 VBScript 就是那把瑞士军刀 :不装任何环境、双击就能跑、几十行解决一次重复劳动。这篇把语法、过程与函数、错误处理 三块基本功一次讲透,每段代码都能直接存成 .vbs 运行。

一、开篇:小脚本解决的大问题

先看三个真实场景,你可能天天在手工干:

  1. 每天下班前把某个目录的配置文件备份一遍(手工复制改名 ×365 天);
  2. 月底统计 20 个服务器日志的报错行数(打开 20 个记事本数数);
  3. 批量修改 500 个文件的命名规则(F2 改名改到手抽筋)。

这些活儿的共同点:逻辑简单、重复量大、环境受限 。用 VBScript,一个脚本全搞定,而且 Windows 出厂自带(cscript.exe / wscript.exe),这是它至今不过时的理由。

二、运行环境与第一个脚本

两种宿主,两种体验:

宿主 行为 适合
wscript.exe 弹窗(MsgBox)交互 双击运行、给非技术同事用
cscript //nologo xx.vbs 控制台输出(WScript.Echo) 调试首选,日志能落盘能重定向

第一个脚本(存为 hello.vbs):

vbs 复制代码
' hello.vbs ------ 单引号是注释,Rem 也是
Option Explicit          ' 强制声明变量,必写!防手滑第一名
Dim name
name = "王文峰"
WScript.Echo "你好," & name & "!当前时间:" & Now()

运行:cscript //nologo hello.vbs。看到输出,环境就通了。

💡 Option Explicit 必须是第一条语句。它能抓住 90% 的拼写 bug(变量名写错变新变量),是 VBScript 版的"严格模式"。

三、语法精讲:变量、运算符、流程控制

1. 变量与类型

VBScript 只有一种数据类型 Variant(变体),按使用场景自动呈现子类型:

vbs 复制代码
Option Explicit
Dim a, b, c
a = 100                 ' 数字(Integer/Long)
b = "text"              ' 字符串
c = True                ' 布尔
Dim d
d = #2026-10-19#         ' 日期字面量用 # 包裹

' 显式类型转换(都是函数)
WScript.Echo CStr(a), CInt("123") + 1, CDate("2026/10/19"), CDbl("3.14")
WScript.Echo TypeName(a)      ' "Integer",排查类型问题很有用

2. 运算符(三个高频坑)

类别 运算符 坑点
字符串连接 & 用 & 不用 + ------"1" + 1 是 2,"1" & 1 是 "11",语义完全不同
比较 = <> > < 空串和 0 比较有惊喜,先 Len() 判空
模糊匹配 Like 支持 *、?、[a-z],If s Like "*error*" Then

3. 流程控制四件套

vbs 复制代码
' ① If 分支
Dim score
score = 85
If score >= 90 Then
    WScript.Echo "优秀"
ElseIf score >= 60 Then
    WScript.Echo "及格"
Else
    WScript.Echo "不及格"
End If

' ② Select Case(多分支首选,比嵌套 If 清爽)
Select Case Weekday(Now())
    Case 1, 7 : WScript.Echo "周末,休息"
    Case Else : WScript.Echo "工作日,搬砖"
End Select

' ③ For:固定次数
Dim i, s
s = 0
For i = 1 To 10 Step 2      ' 步长 2:1,3,5,7,9
    s = s + i
Next
If i > 100 Then Exit For    ' 提前跳出

' ④ Do While / Do Until:条件循环(替代 While...Wend,老写法别用了)
Dim n
n = 0
Do While n < 3
    n = n + 1
Loop
Do
    n = n - 1
Loop Until n <= 0

' ⑤ For Each:遍历集合(数组、文件夹、字典都靠它)
Dim f
For Each f In Array(1, 2, 3)
    WScript.Echo f
Next

4. 常用内置函数(字符串为王)

vbs 复制代码
Dim str : str = "  vbScript,好用!  "
WScript.Echo Len(str)                    ' 长度
WScript.Echo Trim(str)                   ' 去首尾空格
WScript.Echo InStr(str, "Script")        ' 子串位置(找不到=0)
WScript.Echo Mid(str, 3, 2)              ' 截取
WScript.Echo Replace(str, "!", "。")     ' 替换
WScript.Echo LCase(str)                  ' 转小写

' Split / Join:文本与数组的双向转换,处理 CSV/日志行的神器
Dim arr : arr = Split("a,b,c", ",")
WScript.Echo UBound(arr)                 ' 最大下标 = 2(注意从 0 起)
WScript.Echo Join(arr, "|")              ' a|b|c

' 日期三兄弟
WScript.Echo DateAdd("d", 7, Now())      ' 加 7 天
WScript.Echo DateDiff("d", #2026-01-01#, Now())   ' 相差天数
WScript.Echo FormatDateTime(Now(), 2)    ' 短日期格式

5. 数组:动态扩容

vbs 复制代码
Option Explicit
Dim arr()          ' 声明动态数组(不能直接用)
ReDim arr(2)       ' 分配 3 个元素(0~2)
arr(0) = "甲" : arr(1) = "乙" : arr(2) = "丙"

ReDim Preserve arr(4)   ' 扩到 5 个元素,**Preserve 保留原有数据**
arr(3) = "丁"
Dim item
For Each item In arr
    WScript.Echo item
Next

⚠️ ReDim Preserve 只能改最后一维,这是硬性限制。

四、过程与函数:Sub 与 Function 的分工

1. Sub vs Function(必考)

对比 Sub(子过程) Function(函数)
返回值 无 有(通过"给函数名赋值"返回)
调用方式 Call Name(args) 或直接 Name args 可以嵌在表达式里 x = Name(args)
适合 执行动作:写日志、发邮件、复制文件 计算结果:统计、格式化、校验
vbs 复制代码
Option Explicit

' ---- Sub:执行动作,无返回值 ----
Sub WriteHello(name)
    WScript.Echo "[" & Now() & "] 你好:" & name
End Sub

' ---- Function:给函数名赋值就是返回值 ----
Function Max(a, b)
    If a > b Then
        Max = a          ' ← 返回值靠"函数名 = 值"
    Else
        Max = b
    End If
End Function

' ---- 调用 ----
WriteHello "王文峰"                ' 简写形式
Call WriteHello("神秘小峯")         ' Call 形式
WScript.Echo "较大值:" & Max(3, 9)

2. 参数默认 ByRef(VBScript 第一大坑)

vbs 复制代码
Sub AddOne(ByVal n)      ' ByVal:传副本,改了不影响外面
    n = n + 1
End Sub

Sub AddOneRef(ByRef n)   ' ByRef(默认):传引用,改外面变量
    n = n + 1
End Sub

Dim x : x = 1
AddOne x      : WScript.Echo x   ' 1(没变)
AddOneRef x   : WScript.Echo x   ' 2(变了!)

💡 不写 ByVal/ByRef 就是 ByRef ------忘传 Call 加括号时行为还会变。所以团队约定:参数一律显式写 ByVal,除非确实要改外部变量。

3. 退出与作用域

vbs 复制代码
Function FindLine(lines, keyword)
    Dim i
    For i = 0 To UBound(lines)
        If InStr(lines(i), keyword) > 0 Then
            FindLine = i
            Exit Function      ' 找到就走,不必跑完循环
        End If
    Next
    FindLine = -1              ' 约定:-1 表示没找到
End Function
  • 脚本级变量 (Dim 在所有 Sub 外面)全局可见,Option Explicit 下全局变量各过程都能访问;
  • 过程级变量 (Sub/Function 内 Dim)过程结束即释放;
  • 没有模块/命名空间 ,大脚本靠"前缀命名"防重名:Log_Write、Util_TrimAll。

五、错误处理:On Error Resume Next 是唯一武器

VBScript 没有 try-catch ,错误处理全靠 On Error Resume Next + Err 对象,这是本篇的重中之重。

1. 标准姿势:出错 → 检查 → 清理

vbs 复制代码
Option Explicit
Dim fso, ts
Set fso = CreateObject("Scripting.FileSystemObject")

On Error Resume Next        ' 出错不中断,继续执行下一行
Set ts = fso.OpenTextFile("C:\不存在\log.txt", 8, True)

If Err.Number <> 0 Then     ' ← 每次 Resume Next 后必须立刻检查
    WScript.Echo "写日志失败!错误号:" & Err.Number
    WScript.Echo "描述:" & Err.Description
    WScript.Echo "来源:" & Err.Source
    Err.Clear               ' 清空 Err,避免污染后续判断
    WScript.Quit 1          ' 非 0 退出码,方便计划任务监控
End If

On Error GoTo 0             ' 恢复"遇错即停"的默认行为
ts.WriteLine "正常写入"
ts.Close

Err 对象三件套 :Number(错误号,0 表示无错)、Description(人话描述)、Source(出错对象/组件)。用完记得 Err.Clear。

2. 手动抛错:Err.Raise

vbs 复制代码
Function LoadConfig(path)
    Dim fso : Set fso = CreateObject("Scripting.FileSystemObject")
    If Not fso.FileExists(path) Then
        ' vbObjectError + 自定义号,避免与系统错误号冲突
        Err.Raise vbObjectError + 1001, "LoadConfig", "配置文件不存在:" & path
        Exit Function
    End If
    LoadConfig = "ok"
End Function

' 调用方统一捕获
On Error Resume Next
Dim r : r = LoadConfig("C:\app\config.ini")
If Err.Number <> 0 Then
    WScript.Echo "调用失败:" & Err.Description
    Err.Clear
End If
On Error GoTo 0

3. 两个必须知道的坑

  • 错误处理不跨过程 :On Error Resume Next 只在当前过程内生效,每个 Sub/Function 都要自带一套"Resume Next → 检查 Err";
  • Resume Next 会吞掉所有错 :忘记检查 Err.Number,脚本会"假装成功"地跑完------这是 VBS 脚本事故的第一来源 。原则:On Error Resume Next 之后紧跟 If Err.Number <> 0。

4. 统一错误处理模板(推荐收藏)

vbs 复制代码
Option Explicit
Dim fso : Set fso = CreateObject("Scripting.FileSystemObject")
Const LOG_PATH = "C:\logs\job.log"

Sub Log(msg)
    Dim ts
    Set ts = fso.OpenTextFile(LOG_PATH, 8, True)   ' 8=追加模式,True=不存在则创建
    ts.WriteLine FormatDateTime(Now(), 3) & "  " & msg
    ts.Close
End Sub

Sub HandleError(source)
    Log "[ERROR][" & source & "] " & Err.Number & ":" & Err.Description
    Err.Clear
End Sub

Sub DoWork()
    On Error Resume Next
    ' ... 你的业务代码 ...
    If Err.Number <> 0 Then HandleError "DoWork" : Exit Sub
    On Error GoTo 0
    Log "[INFO] 任务完成"
End Sub

六、实战:目录巡检 + 日志脚本

把上面三块知识拼起来------统计目录文件数、找超期文件、全程带日志,直接可用:

vbs 复制代码
' patrol.vbs ------ 用法:cscript //nologo patrol.vbs D:\data 30
Option Explicit

Dim fso, folderPath, days, logFile
Set fso = CreateObject("Scripting.FileSystemObject")

' ---- 参数校验 ----
If WScript.Arguments.Count < 2 Then
    WScript.Echo "用法:cscript patrol.vbs <目录> <天数>"
    WScript.Quit 2
End If
folderPath = WScript.Arguments(0)
days = CInt(WScript.Arguments(1))
logFile = fso.BuildPath(fso.GetParentFolderName(folderPath), "patrol.log")

' ---- 工具函数 ----
Sub Log(msg)
    Dim ts
    Set ts = fso.OpenTextFile(logFile, 8, True)
    ts.WriteLine FormatDateTime(Now(), 3) & "  " & msg
    ts.Close
End Sub

Function CountFiles(folder)
    Dim f, n : n = 0
    For Each f In folder.Files
        n = n + 1
    Next
    CountFiles = n
End Function

' ---- 核心巡检 ----
Sub Patrol(folderPath, days)
    On Error Resume Next
    Dim folder : Set folder = fso.GetFolder(folderPath)
    If Err.Number <> 0 Then
        Log "[ERROR] 目录不可访问:" & folderPath & " / " & Err.Description
        Err.Clear
        Exit Sub
    End If
    On Error GoTo 0

    Log "[INFO] 开始巡检:" & folderPath
    Log "[INFO] 文件总数:" & CountFiles(folder)

    Dim f, stale : stale = 0
    For Each f In folder.Files
        If DateDiff("d", f.DateLastModified, Now()) > days Then
            stale = stale + 1
            Log "[WARN] 超期文件:" & f.Name & "(最后修改 "
            Log "        " & DateDiff("d", f.DateLastModified, Now()) & " 天前)"
        End If
    Next

    Log "[INFO] 超期文件共 " & stale & " 个,巡检结束"
    WScript.Echo "巡检完成,详见 " & logFile
End Sub

Patrol folderPath, days

跑一次,日志长这样:

复制代码
10:21:33  [INFO] 开始巡检:D:\data
10:21:33  [INFO] 文件总数:128
10:21:33  [WARN] 超期文件:old_backup.zip(最后修改
10:21:33          47 天前)
10:21:33  [INFO] 超期文件共 1 个,巡检结束

丢进任务计划程序每天 18:00 跑一次,一个免维护的巡检工具就有了。

七、避坑清单(血泪总结)

坑 症状 解法
忘写 Option Explicit 变量名写错变新变量 永远第一行
用 + 连接字符串 "1"+1 变 2 一律用 &
参数不写 ByVal 外部变量被悄悄改掉 显式 ByVal
Resume Next 后不检查 脚本"假装成功" 紧跟 If Err.Number <> 0
双引号写成中文引号 语法错误,一脸懵 切英文输入法
路径反斜杠不转义 VBS 里 \ 就是 \ 不需要 \\(别拿 Java 习惯套)
中文乱码 输出/日志乱码 文件另存为 ANSI/UTF-8 with BOM ,cscript 下用 chcp 936

八、总结与自测清单

  • ✅ cscript //nologo 是调试神器,wscript 弹窗是交付神器;
  • ✅ Option Explicit + & 连接 + 显式 ByVal,三件套防住大半坑;
  • ✅ Sub 管"做事",Function 管"算数",返回值靠给函数名赋值;
  • ✅ 字符串处理记 Split/Join/InStr/Replace 四兄弟;
  • ✅ 错误处理唯一姿势:On Error Resume Next → 立刻检查 Err.Number → Err.Clear → On Error GoTo 0;
  • ✅ 错误处理不跨过程,每个过程自带一套;
  • ✅ 日志 Sub 是脚本的"保险丝",写脚本先写日志。

下一篇:《进阶篇------FSO 文件系统、字典对象 Dictionary 与 WMI 查询》------让小脚本具备真正干活的能力,敬请关注!

🎯 学习教程(传送门)

序号 专栏 学习内容 当前状态
01 JAVA 从入门到进阶的系统知识 持续写作中......
02 Oracle 数据库从用法到实战 创作中......
03 vbs脚本 手把手教你做脚本 完善中......
04 IDEA 牛逼哄哄的编程利器 编写中......
05 面试 吐血整理的面试技巧 更新中......

🔥 往期文章

🧭 精选往期好文,更多请移步 我的博客主页

👍 点赞 + ⭐ 收藏 + 💬 评论,一键三连走起!

你们的支持,是我持续创作的最大动力~

✨ 以上就是今天的全部内容,关注我,技术之路不迷路!

📖 本人详解

✍️ 作者:王文峰,参与 CSDN 2020 年度博客之星评选,《Java王大师王天师》,外号:神秘小峯 / 山峯

🏮 中国国学、传统文化与代码爱好者的程序人生,期待你的关注的支持!

🔗 转载说明:务必注明来源(注明:作者:王文峰哦)

相关推荐
Helix25016 天前
Electron、WebView 框架与 HTA 对比:桌面应用选型、安全性与现代替代方案
前端·javascript·electron·webview·vbscript·hta·本地html应用
山峰哥4 个月前
VB事件驱动编程实战:从零到一搭建完整管理系统
前端·数据库·性能优化·深度优先·vb
cdbqss15 个月前
VB2026 菜单生成基类 BqGetMenuStrip
数据库·经验分享·学习·oracle·vb
专注VB编程开发20年6 个月前
VBA/VB6 ADO数据库查询jet+只读更快
开发语言·数据库·ado·vb
Access开发易登软件9 个月前
Access自动生成PPT报告完全指南
数据库·powerpoint·vba·vb·access·access开发
secondyoung10 个月前
WPS宏使用:一键批量调整图片与表格格式
经验分享·word·lua·markdown·wps·vb
課代表1 年前
Visual Basic.NET 的特性
多态·继承·封装·overload·vb·重载·visual basic
Nukepayload21 年前
演练:使用VB开发多智能体协作的荣格八维分析器
ai·avalonia·vb·智能体·工具调用·实时反馈·智能体协同
LingDong Jey2 年前
【案例】Excel使用宏来批量插入图片
vb·excel宏·批量插入图片