类对象支持库(不是扁平命令)。路径:支持库 → 扩展类库 → 进程类。
类型名必须写完整「进程类」。声明时自动创建,一般无需再调 创建*。
与扁平「进程操作」不同:本类侧重 启动外部程序 + 重定向标准输入/输出/错误,适合抓命令回显、做简易终端壳。枚举/结束任意 PID、取图标等仍用 进程操作(扁平)。
硬约束
- 类型名必须写「进程类」。
- 方法调用必须带括号。
启动的第一参是 可执行文件路径或系统能解析的程序名(如cmd.exe、powershell.exe、完整.exe路径);第二参是 参数字符串(不含程序名本身)。- 默认 隐藏窗口 并把 stdout/stderr 接到管道;读写文本按 UTF-8。
- 没有「一条命令的回应已结束」协议:只有「进程已退出」或「管道里又写出了若干字节」可感知。一次性命令用
读全部();常驻壳优先数据到达(&回调)(同 TCP),也可用读等待()/接收()。 - 管道重定向 不是 Windows 真控制台(ConPTY):无彩色/光标/
cls等完整终端行为。
能执行什么
启动(程序路径, [参数], [显示窗口]) 本质是 CreateProcess:能启动本机任意可执行文件(权限与路径允许的前提下),不限于 CMD。
| 目标 | 示例 |
|---|---|
| CMD 跑一条就退出 | p.启动("cmd.exe", "/c dir") 再 p.读全部() |
| CMD 保持会话(简易壳) | p.启动("cmd.exe", "/K"),用 写 + 数据到达(或 读等待) |
| Windows PowerShell 一条 | p.启动("powershell.exe", "-NoProfile -Command \"Get-Date\"") |
| PowerShell 保持会话 | p.启动("powershell.exe", "-NoLogo -NoExit"),同上 写 + 数据到达 |
| PowerShell 7+(若已安装) | p.启动("pwsh.exe", "-NoLogo -Command \"…\"") |
任意 .exe |
p.启动("C:\\Tools\\app.exe", "--flag 1") |
| 显示其窗口(不抓输出场景) | p.启动("notepad.exe", "", 真) |
说明:
- 不能把整句
"cmd /c dir"塞进第一参当「命令行」;程序与参数要拆开(或使用你自备的包装 exe)。 - 批处理:
p.启动("cmd.exe", "/c C:\\a.bat")。 - 脚本:
p.启动("powershell.exe", "-File C:\\a.ps1")。 - 中文乱码:先让子进程用 UTF-8(如 CMD 参数里加
chcp 65001>nul & …),或优先 PowerShell。
启动 参数怎么写
进程类自身(三个形参)
| 形参 | 类型 | 含义 |
|---|---|---|
| 程序路径 | 文本 | CreateProcess 的可执行文件。写 cmd.exe / powershell.exe / pwsh.exe / 完整 .exe 路径均可(系统能解析即可)。 |
| 参数 | 文本,可选 | 不含程序名 的参数串,原样传给该程序。空文本=无参数。 |
| 显示窗口 | 逻辑,可选,默认假 | 假=隐藏并适合抓输出;真=显示该程序窗口(记事本等)。 |
进程类不解析 /c、-Command 等——那些是 cmd / PowerShell 自己的开关,写在第二参里。
常用:cmd.exe 第二参
| 第二参写法 | 行为 |
|---|---|
/c 命令 |
执行一条(可含 &&、&、重定向)后 退出 → 配 读全部() |
/c chcp 65001>nul & 命令 |
同上,并尽量用 UTF-8 代码页,减少中文乱码 |
/c "路径含空格\a.bat" 参数 |
跑批处理;路径有空格时自行按 cmd 规则加引号 |
/K 或 /K chcp 65001>nul |
执行后 不退出(交互壳)→ 配 数据到达 + 写(行+"\n") |
/K 命令 |
先执行命令再保持会话 |
说明:/c、/K 后面整段都是 cmd 命令行语法(内部命令如 dir/echo/cd,或再调别的 exe)。进程类只负责把第二参交给 cmd.exe。
常用:powershell.exe / pwsh.exe 第二参
| 第二参写法 | 行为 |
|---|---|
-NoProfile -Command "表达式" |
执行表达式后退出 → 读全部() |
-NoProfile -File "C:\a.ps1" |
执行脚本后退出 |
-NoLogo -NoExit |
进入交互会话不退出 → 数据到达 + 写 |
-NoLogo -NoExit -Command "…" |
先跑一句再保持会话 |
引号:Y++ 字符串里写 PowerShell 时,内层双引号需转义,例如
"-NoProfile -Command \"Get-Date\""。
不支持 / 易混
| 误解 | 实际 |
|---|---|
第一参写 cmd /c dir |
应 启动("cmd.exe", "/c dir") |
| 以为进程类内置「所有 cmd 内部命令」API | 没有;内部命令通过启动 cmd.exe 执行 |
交互壳用 读全部() 等「本条结束」 |
壳不退出则永不等到;改 数据到达 / 读等待,或每次 /c 新进程 |
| 当真 ConPTY 终端用 | 仅管道重定向,无彩色/cls 等完整控制台 |
两种用法(务必分清)
A. 一次性命令(推荐:执行 → 等结束 → 读回)
子进程 跑完会退出。读全部() 会等到退出(或超时),这就是「等待回应完成再读」。
进程类 p
如果 (p.启动("cmd.exe", "/c echo hi") == 假) {
输出(p.取错误())
} 否则 {
文本框1.内容 = p.读全部() // 阻塞到进程结束;勿在超长任务里卡死 UI
}
PowerShell 同理:
进程类 p
如果 (p.启动("powershell.exe", "-NoProfile -Command \"Get-Process | Select-Object -First 3\"")) {
文本框1.内容 = p.读全部(15000)
}
界面事件里若命令可能很久,请自己加超时:读全部(毫秒),或放到线程里跑。
B. 常驻壳(推荐:数据到达 实时收,同 TCP)
cmd /K、powershell -NoExit 不会在每条命令后退出,因此:
- 不能用
读全部()等「这条命令结束」(会一直等到整个 shell 退出)。 - 可以像 TCP 一样实时收:注册
数据到达(&回调),有标准输出即在 UI 线程 回调。
| 步骤 | 方法 |
|---|---|
| 注册回调 | 数据到达(&收到) / 可选 进程退出(&退了)(须在启动前) |
| 启动并保持 | 启动("cmd.exe", "/K …") |
| 发送 | 写(行 + "\n") |
| 接收 | 回调里拿 文本 数据(不必定时器) |
进程类 shell
函数 收到(文本 数据) {
输出框.加入文本(数据)
}
函数 退了(整数 码) {
输出("壳退出 code=" + 到文本(码))
}
函数 主窗口.创建完毕 () {
shell.数据到达(&收到)
shell.进程退出(&退了)
如果 (shell.启动("cmd.exe", "/K chcp 65001>nul") == 假) {
输出框.文本 = shell.取错误()
}
}
函数 发送一行 (文本 行) {
shell.写(行 + "\n")
}
备选:读等待(超时) / 接收(超时)(阻塞等到有输出;UI 线程勿长时间堵,可放线程池)。定时器轮询 读() 也可用,但不是必须。
说明:无论事件还是 读等待,都只表示「又有若干字节」,不表示「本条命令的全部输出已结束」。若要严格「一条命令整段回显」,请改用模式 A:每次 /c + 读全部()。
若你坚持「每条命令:启动 → 等结束 → 读回」,不要保持会话,改为每次:
启动("cmd.exe", "/c " + 用户输入) + 读全部()。
------|------|
| 启动并保持 | 启动("cmd.exe", "/K …") |
| 发送 | 写(行 + "\n") |
| 接收(阻塞等到有输出或超时) | 读等待(超时) 或同义名 接收(超时) |
界面程序请把监听放在线程池,避免卡住 UI:
进程类 shell
整数 g_听池
文本 g_待显
逻辑 g_听停
函数 听循环 () {
当 (g_听停 == 假 且 shell.是否运行中()) {
文本 t = shell.读等待(200) // 有输出就返回;200ms 无数据则空转一圈
如果 (t != "") {
g_待显 = g_待显 + t
}
}
}
函数 主窗口.创建完毕 () {
如果 (shell.启动("cmd.exe", "/K chcp 65001>nul") == 假) {
输出框.文本 = shell.取错误()
返回 ()
}
g_听停 = 假
g_听池 = 创建线程池(1)
投递任务(g_听池, &听循环)
// 另用短定时器或空闲回调把 g_待显 刷到输出框(仅搬文本,不轮询进程)
}
函数 发送一行 (文本 行) {
shell.写(行 + "\n") // 发送后,听循环里的 读等待 会收到回显
}
说明:读等待 在「有任意输出」时返回,仍不表示「本条命令的全部输出已结束」(shell 不会为此发结束信号)。若要严格「一条命令整段回显」,请改用模式 A:每次 /c + 读全部()。
定时器轮询 读() 仍然可用,只是实现监听的一种方式,不是必须。
若你坚持「每条命令:启动 → 等结束 → 读回」,不要保持会话,改为每次:
启动("cmd.exe", "/c " + 用户输入) + 读全部()。
快速开始
进程类 p
如果 (p.启动("cmd.exe", "/c echo hi")) {
输出(p.读全部())
} 否则 {
输出(p.取错误())
}
进程类/创建
共 1 条。
创建进程
- 签名:
通用 创建进程() - 说明:创建一个进程会话。一般直接写「进程类 p」即可。用于启动外部程序并读取标准输出(与支持库「进程操作」无关)。
进程类/方法
共 19 条。
启动
- 签名:
逻辑 启动(文本 程序路径, [文本 参数], [逻辑 显示窗口=假]) - 说明:启动外部程序;成功返回真。默认隐藏窗口并捕获输出。可启动 cmd / PowerShell / 任意 exe(见上文「能执行什么」)。
- 参数一│文本 程序路径: 可执行文件(如
cmd.exe、powershell.exe、完整路径)。 - 参数二│[文本 参数=”“]: 命令行参数(不含程序名)。
- 参数三│[逻辑 显示窗口=假]: 真=显示窗口。
置标准输入
- 签名:
逻辑 置标准输入(管道类 子进程读端) - 说明:把管道类的读端交给子进程标准输入。须在启动前调用。设置后请用管道父写端发送,勿再用
写()。 - 参数一│管道类 子进程读端: 匿名管道读端;父进程用对应写端发送
置标准输出
- 签名:
逻辑 置标准输出(管道类 子进程写端) - 说明:把管道类的写端交给子进程标准输出。须在启动前调用。设置后
读()/读全部()不再含这段输出,请从父读端接收。 - 参数一│管道类 子进程写端: 匿名管道写端;父进程用对应读端接收
置标准错误
- 签名:
逻辑 置标准错误(管道类 子进程写端) - 说明:把管道类的写端交给子进程标准错误。优先于默认「错误并入标准输出」。
- 参数一│管道类 子进程写端
清除标准句柄
- 签名:
无 清除标准句柄() - 说明:取消已设置的标准输入/输出/错误管道,恢复内置重定向。
写
- 签名:
逻辑 写(文本 内容) - 说明:向标准输入写入文本(UTF-8)。交互壳每行末尾须带
\n。 - 参数一│文本 内容: 写入内容。
数据到达
- 签名:
无 数据到达(子程序指针 回调) - 说明:注册「标准输出有新数据」回调(同 TCP类)。须在启动前注册;传 0 清除。UI 线程触发;形参
文本 数据。 - 参数一│子程序指针 回调: 形如
函数 收到(文本 数据)。
进程退出
- 签名:
无 进程退出(子程序指针 回调) - 说明:注册「子进程已退出」回调;须在启动前;传 0 清除。UI 线程;形参
整数 退出码。
读
- 签名:
文本 读() - 说明:读取 当前已有 的标准输出(不阻塞)。无数据立刻返回空文本。
读等待
- 签名:
文本 读等待([整数 超时毫秒=-1], [整数 最大字节=0]) - 说明:阻塞直到有标准输出、进程退出、或超时。有数据即返回(不必等进程结束)。UI 勿长时间堵在界面线程。
- 参数一│[整数 超时毫秒=-1]:
<0无限等;0等同读();>0最多等这么久 - 参数二│[整数 最大字节=0]:
≤0不限制
接收
- 签名:
文本 接收([整数 超时毫秒=-1], [整数 最大字节=0]) - 说明:同
读等待()(发送/接收风格别名)。
读全部
- 签名:
文本 读全部([整数 超时毫秒=-1]) - 说明:等待进程结束(或超时)后返回全部标准输出。仅适用于会退出的一次性进程。
- 参数一│[整数 超时毫秒=-1]: ≤0=无限等待。
等待
- 签名:
逻辑 等待([整数 超时毫秒=-1]) - 说明:等待子进程退出;返回真=已退出。
- 参数一│[整数 超时毫秒=-1]: ≤0=无限等待。
结束
- 签名:
逻辑 结束() - 说明:强制结束子进程。
是否运行中
- 签名:
逻辑 是否运行中() - 说明:子进程是否仍在运行。
取进程ID
- 签名:
整数 取进程ID() - 说明:取子进程 PID。
取退出码
- 签名:
整数 取退出码() - 说明:取退出码;仍在运行时返回 -1。
取错误
- 签名:
文本 取错误() - 说明:取最后一次失败原因。
重置
- 签名:
无 重置() - 说明:结束并清理会话。
易错对照
| 错误 | 正确 |
|---|---|
| 类型写成「进程」 | 必须「进程类」 |
读全部输出() |
方法名是 读全部() |
交互壳里调 读全部() 等「这条命令结束」 |
进程不退出会一直等;改用 数据到达 / 读等待 或每次 /c 新进程 |
| 以为必须用定时器才能回显 | 否;优先 数据到达(&回调)(同 TCP);读等待/定时器只是备选 |
| 与扁平「运行/执行」混淆 | 要抓 stdout/stdin → 用本类;只要弹程序 → 扁平亦可 |
第一参写整句 cmd /c dir |
拆成 启动("cmd.exe", "/c dir") |
界面里对长任务无限 读全部() |
加超时,或放到线程 |