局域网打印助手

SKILL运维和基础设施
运维和基础设施 未标注权限 许可证不明确
安装这个技能

在 Windows 上使用本机已安装的打印机打印 PDF、图片、Word 或 Excel 文件,自动安装打印机驱动,并做打印环境体检(驱动 / WiFi / 连通性 / 打印机状态);默认黑白打印且默认机即硬件黑白机,要彩色必须二次确认(`--color --confirm-color` 同时传),以及查询打印机与队列、取消指定任务。仅适用于 Windows 本机打印。当用户提到「打印文件」「装打印机驱动」「打印机打不出来 / 连不上」「检查打印机环境」时使用。

一句话选型结论

按资料字段整理

局域网打印助手是运维和基础设施类的 Agent Skill,安装方式未标注,权限级别未标注,许可证不明确,有可直接复制的安装命令。技能本质是给模型读的说明书,效果取决于模型与客户端;装完先用一个小任务验证,再放进正式流程。

分类运维和基础设施 安装方式未标注 权限级别未标注权限 许可证许可证不明确
累计安装 未标注 本周 未标注
GitHub 星标 未标注 仓库 未标注
下载量 未标注 技能市场下载数
权限级别 未标注权限 安装前请确认风险范围
许可证 许可证不明确 未说明

安装

未标注
在支持 Skills 的客户端里执行,装完问一句「你有哪些技能」验证
skillhub install user_f43c4493/wsd20260901
  1. 1
    确认客户端支持

    确认你的客户端支持 Skills(Claude、Codex、Cursor 等),并升级到较新的版本。

  2. 2
    拿到技能文件

    执行上面的命令安装;也可以把仓库里的 SKILL.md 手动放进客户端的 skills 目录。

  3. 3
    刷新技能列表

    重新打开客户端,或刷新技能列表,让新放进来的技能被加载。

  4. 4
    验证是否生效

    问一句「你有哪些技能」,确认列表里出现它,再拿一个小任务试跑。

技能档案

运维和基础设施
字段来自技能仓库与公开索引,中文说明由本站标注
作者 / 维护方user_f43c4493仓库 未标注 · 版本 未标注
宿主客户端未标注技能可被这些客户端加载
安装方式未标注安装包 community
权限级别未标注权限安装前请确认风险范围
许可证未说明许可证不明确,商用前请自行确认条款
仓库可用性available技能仓库当前是否可访问
最近核验2026-11-06上游最后核验时间 · 数据更新 2026-11-06
正文体量31.3 KBSKILL.md 原文大小,越大说明说明书写得越细

典型使用场景

3 类
按分类整理的常见用法,具体以 SKILL.md 为准
查服务与日志

按现象定位服务状态与日志线索。

写部署与巡检脚本

把重复的部署、巡检写成脚本。

故障排查

按步骤排查网络、依赖与配置。

选择建议

装之前先看这几条
按条目字段给出的判断,不替你决定用不用

值得选的地方

  • 有可直接复制的安装命令,不用自己翻文档找入口。

先想清楚的地方

  • 没有标注权限级别,实际能做什么要装好后确认。
  • 许可证不明确,商用或二次分发前先到仓库确认条款。
  • 没有做站内核验,内容以作者仓库为准。
  • 技能只是说明书,实际效果取决于模型与客户端,装完先用小任务试一遍。

更适合

  • 需要在运维和基础设施场景里给模型补一套做法的人。
  • 愿意先读一遍 SKILL.md、确认它会让模型做什么的人。

不太适合

  • 对许可证要求很严、必须明确可商用的人。
  • 只想装完就自动变强、不打算看说明书的人。

同类对比

6 个同类
同分类里挑最接近的几条,字段以各自详情页为准
技能权限级别安装方式累计安装宿主客户端安装命令
局域网打印助手当前 未标注权限 未标注 未标注 未标注 有
Azure 部署 调用外部服务 GitHub 仓库 664.2 万 Codex、Claude、Cursor 有
Azure diagnostics 问题管理 调用外部服务 GitHub 仓库 657.6 万 Codex、Claude、Cursor 有
Azure aigateway 部署 调用外部服务 GitHub 仓库 655.3 万 Codex、Claude、Cursor 有
Azure AI 搜索 调用外部服务 GitHub 仓库 651.4 万 Codex、Claude、Cursor 有
Azure Cloud migrate 部署 调用外部服务 GitHub 仓库 650.7 万 Codex、Claude、Cursor 有

SKILL.md 全文

31.3 KB
模型实际读到的说明书原文,来自技能仓库

> 📌 1.5.0(本次):改为「一套源码、两个分发」结构 —— 本包与
> lan-print-macos(macOS 版)共用同一份 print_tool.py,平台差异收敛在内部的
> 平台后端(_win_* / _mac_*)与各包自己的 bootstrap / config.json / 本文档。
> 这样两端不会再各自漂移。
> 本次新增同楼层多台打印机支持(alt_printers,见下文),对既有单打印机配置无影响。
> ⚠️ 本包内的 print_tool.py 与线上 1.2.1 的 Windows 代码路径行为一致,
> 平台分支以外的函数体逐字未改。

Windows 打印(lan-print)

本技能通过同目录的 bootstrap.ps1 操作 Windows 已安装的打印机。Skill ZIP 不包含 EXE 或 CMD;首次运行由脚本下载并校验 Windows x64 运行组件,之后复用本机缓存。无需访问 GitHub、安装 Python 或安装 SumatraPDF。

配置(客户无需手工指定)

目标打印机的信息写在随包 config.json,客户装好即用,不必输任何参数:

字段 说明
printer_name 目标打印机名
printer_ip 打印机 IP(自动建端口用)
driver_model 驱动名,必须与 Windows 驱动库里的显示名完全一致
driver_inf_name 驱动包内真正的 inf 文件名(精确指定,避免选错)
driver_provider / driver_version 驱动厂商与版本,仅作记录
wifi_ssid 打印所要求的 WiFi
print_monochrome_default 打印是否默认黑白(由启动器注入 --monochrome,见下)
driver_share_id 驱动包分享页 id(现解析,见下)
driver_package_page 驱动包下载页(失败时展示)
runtime 运行组件来源(url / sha256),替换分发渠道时只改这里

> ⚠️ 驱动包的外层目录名可能是骗人的。当前 Xerox 驱动包外层目录叫
> UNIV_5.1009.1.0_PS_x64_Driver.inf(一个带 .inf 后缀的目录),
> 而真正的 inf 在里面叫 x3UNIVP.inf。名字对不上,靠猜必错 ——
> 所以 driver_inf_name 是精确指定,不是可选项。

打印机解析顺序:--printer > 环境变量 PRINTER_NAME > config.json > Windows 默认打印机。
config.json 缺失或损坏不会报错,自动降级。

驱动包直链为什么要现解析

分享页给出的 OSS 直链签名有效期仅约 120 秒,固化进分发包必然过期。
所以配置里只存 driver_share_id,安装驱动时现解析,下载重试时也会重新签名。
(实现在 resolve_share_link() / driver_download_url()。)

⚠️ 驱动安装的两个致命坑(换驱动前必读)

坑 1:「装入驱动库」≠「注册进打印子系统」,这是两件事

动作 实际效果 Get-PrinterDriver 可见?
pnputil /add-driver 把 inf 放进 Windows 驱动库(driver store) ❌ 看不见
Add-PrinterDriver 注册进打印子系统,Add-Printer 才能用它 ✅ 可见

只做前者 → 会出现「pnputil 报告成功,但 Add-Printer 仍找不到驱动」的假成功。
这正是「反复提示装成功的还是旧驱动」的根因。

坑 2:V4 打印驱动不支持 -InfPath

V4 驱动(INF 里 PackageAware=TRUE,如当前用的 Xerox GPD)执行
Add-PrinterDriver -InfPath 会报「为此操作指定的一个或多个参数值无效」——
这是预期行为,不是失败。若把它当第一步,就会被误判为失败并退回 pnputil,
从而掉进坑 1。

正确顺序(print_tool.py 与 lan-print-install.ps1 均已按此实现):

① Get-PrinterDriver 按名查 → 已在打印子系统 ? 直接过
② Add-PrinterDriver -Name "<驱动名>"          → 成功即完成
③ pnputil /add-driver <inf> /install
   然后**必须**再 Add-PrinterDriver -Name    → 装库后补注册,不可省
④ Add-PrinterDriver -Name -InfPath <inf>     → 仅 V3 驱动有效,最后的兜底

坑 3:端口协议会被旧驱动遗留污染

换品牌后旧的 LPR/515 端口会留在系统里。Xerox 新机走 LPR 可能出现
「任务发出但不打纸」,所以端口不仅要「存在」,Protocol 还要是 RAW、
PortNumber 要是 printer_port(9100)。不匹配时脚本会自动重建端口。

坑 4:Remove-Printer 不能吞错

删除失败时 Add-Printer 会报「指定的打印机已存在」——一个完全看不出根因的错。
所以删除后必须复查对象是否真的消失,没删掉就明确报 PRINTER_REMOVE_FAILED
并提示手工移除,而不是硬着头皮往下走。

调用

先确定本技能目录 <skill_dir>,通过 Windows PowerShell 调用:

bootstrap.ps1  --json <子命令> [参数]

--json 必须放在子命令前。依据进程退出码判断成功或失败;不要用中文关键词猜测结果。

> ### ⚠️ WorkBuddy 宿主里怎么起这个脚本(2026-09-22 实测,务必先读)
>
> 不要从 Bash 里调 powershell.exe —— WorkBuddy 会直接拦截,报
> 「Invoking PowerShell from Bash bypasses PowerShell security checks; use the PowerShell
> tool instead」,命令根本不会执行。而且拦截是按字符串匹配的:哪怕只是
> ls ... && grep ... powershell.exe ... 这种顺带提到,也一样被拒。
>
> 正确做法:用 PowerShell 工具执行,工具内部就是 PowerShell,不需要再套一层 powershell.exe:
>
> powershell > & "<skill_dir>\bootstrap.ps1" --json --out-file "<export_dir>\r.json" <子命令> [参数] >
>
> 另一个实测坑:PowerShell 工具的 stdout 也拿不到(本次 Get-Content ... | 输出 只回了一句
> Command completed with exit code 0,没有正文)。所以——
>
> - --out-file 是这个宿主里唯一可靠的取数通道,每次都带上,别只看 stdout。
> - 脚本跑完后用 Read 工具读那个 JSON 文件(不要依赖终端回显,也不要用
> Get-Content -Raw 指望它打在 stdout 上)。
> - 多个文件连续打印时,可以一次 PowerShell 调用串行执行多条 & $b ... print,
> 每条写各自的 --out-file,再逐个 Read 回来 —— 串行提交也顺带保证了打印顺序。
> - 退出码仍然可信;Command completed with exit code 0 就代表这一步成功。

取回结果:--json + --out-file

powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -File "<skill_dir>\bootstrap.ps1" --json --out-file "C:\temp\result.json" <子命令> [参数]

--json 与 --out-file 都放在子命令前。

为什么需要 --out-file:并不是所有宿主都能可靠捕获子进程的 stdout ——
IDE 内置终端、沙箱环境常常拿不到任何输出(本项目开发过程中实测踩到过)。
落盘回传不经过管道,是更稳的取数方式,建议自动化调用一律带上。

约定 说明
落盘内容 固定为 JSON(UTF-8),与是否传 --json 无关 —— 这条通道是给机器读的
失败也写 成功与失败都会落盘。拿不到 stdout 时,这是唯一能知道失败在哪一步的途径
与退出码一致 文件里的 ok 字段与进程退出码含义相同,两者都可信
写失败不改退出码 主操作可能已成功,不会因回传通道故障而误报失败;此时 stderr 会给出告警,回退读 stdout 即可

调用后先读该文件再判断结果;若文件不存在,说明写入失败(看 stderr 告警),
此时回退用 stdout。

首次运行要求:

  • Windows x64。
  • 联网(首次运行需下载运行组件)。
  • 运行组件缓存于 %LOCALAPPDATA%\WorkBuddy\lan-print\runtime-v1\;每次运行都会校验 SHA-256。
    (目录名 runtime-v1 是缓存槽位标识,与 exe 版本号解耦 —— 升级运行组件时只改 config.json 的
    runtime.file_name / url / sha256,缓存目录保持不变,老用户无需清理旧目录。)
  • 是否需要 wecom-cli 取决于分发渠道(脚本按 URL 自动识别):
    | 渠道 | 地址特征 | 额外依赖 |
    |---|---|---|
    | wsdbrand 分享页(当前默认) | share.wsdbrand.com | 无需任何依赖 |
    | 企业微信微盘 | drive.weixin.qq.com | 需 wecom-cli ≥ 1.1.0 且已完成授权 |
    | 普通 https 直链 | 其他 | 无需任何依赖 |
  • wsdbrand 渠道下发的是 zip 包裹(内层才是真正的 exe/SumatraPDF),启动器会
    自动解压并校验内层文件,无需人工干预。
  • 更换分发渠道只需改 config.json 的 runtime.url,启动器无需改动。

子命令

list
status [--printer "打印机名"]
doctor [--printer "打印机名"] [--auto]
install-driver [--printer "打印机名"]
discover [--subnet "10.20.0.0/24"] [--timeout 1.2]
print --file "文件路径" [--printer "打印机名"] [--copies 1..20] [--monochrome] [--color --confirm-color] [--fit] [--dry-run] [--no-precheck]
cancel [--printer "打印机名"] (--job 任务ID | --all)

discover:换设备后定位打印机

打印机 IP 变了、或不确定设备在哪时用它:并发扫描配置 IP 所在的 /24 网段,
探测 9100(RAW) / 631(IPP) / 515(LPD) 三个打印端口,列出候选设备并标出
当前配置的那个。只做被动端口探测,不发任何打印数据,对设备无副作用。

discover [--subnet 10.20.0.0/24] [--timeout 1.2]

结果里如果当前配置的 IP 不在列表中,说明设备换了地址,把新 IP 填进
config.json 的 printer_ip 即可。

⚠️ 但「找到几个 IP」≠「知道哪台是哪台」

discover 只认端口、不认型号。2026-09-21 实测 17F 网段里同时躺着 4 台打印设备
(2 台 HP LaserJet、1 台 Fuji Xerox、1 台 Xerox AltaLink),端口扫描无法区分
哪台是目标机——猜错就会把文件打到别的机器上(还是别人的部门)。

补一刀只读 SNMP 查询即可拿到厂商 / 型号 / 序列号(标准 MIB,团体名 public,
只读、无副作用,任何 snmpget 工具都行):

OID 含义
1.3.6.1.2.1.1.1.0 sysDescr(厂商 + 型号 + 固件)
1.3.6.1.2.1.1.5.0 sysName(设备主机名)
1.3.6.1.2.1.43.5.1.1.16.1 prtGeneralPrinterName
1.3.6.1.2.1.43.5.1.1.17.1 prtGeneralSerialNumber

实测样例:

10.20.0.243  FUJI XEROX ApeosPort-V C3375 T2   彩色   SN TC100881475085  ← 17F 打印室目标机
10.20.0.244  Xerox AltaLink B8155              黑白   SN HQH261673
10.20.0.240  HP LaserJet MFP M426fdw                 位置标注 EPL TRAINING CENTER
10.20.0.247  HP LaserJet MFP M426fdn

💡 型号命名可当快速判据,能省掉一半的 SNMP 查询:
Xerox / Fuji Xerox 的 C=彩色、B=黑白(故 AltaLink B8155 是黑白机,
ApeosC3375 / ApeosPort-V C3375 是彩色机);HP 的 dw/fdw 是无线款、dn/fdn 是有线款。
⚠️ 顺带影响打印行为:本 skill 的默认机是黑白机(.244,硬件不支持彩色),
所以默认输出必然是黑白;要彩色须显式指向彩色机 .243,并走
--color --confirm-color 的二次确认(见「色彩策略」一节)。

⚠️ prtGeneralPrinterName 是设备端名称,不等于 Windows 本机打印机名
(「17F打印机」是本机自定义的),所以它不能反查目标机 —— 型号只能缩小范围,
最终仍需人来确认(看机身标签 / 问使用人)。确认后再走下面的端口重指流程。

install-driver:已存在打印机时会自动校正

⚠️ 这一点很关键。旧行为是「打印机存在就直接返回已安装」,导致
「驱动失效 → 换新驱动包」时新驱动永远装不上。现在的行为:

情况 动作
打印机不存在 正常创建
已存在且驱动名一致 直接返回,不做任何改动
已存在但驱动名不一致 先 Set-Printer 无损换驱动;失败才 Remove-Printer 后重建

删除重建会在输出里明确标注,不静默删东西。

⚠️ 换 IP 后,端口不会自动跟着变(2026-09-21 实测踩坑)

这是个静默失效的坑:上表「已存在且驱动名一致 → 直接返回」这条捷径,
在 print_tool.py 里是提前 return,跳过了后面的端口校正逻辑。
于是打印机 IP 变了之后重跑 install-driver,只会回一句
「已安装且驱动一致,无需重复安装」,而打印机仍指向旧 IP —— 看着装好了,实际打不出纸。

所以改完 config.json 的 printer_ip 后,必须另做一次端口重指(无损,不删打印机):

Add-PrinterPort -Name "<新IP>" -PrinterHostAddress "<新IP>" -PortNumber 9100
Set-Printer     -Name "<打印机名>" -PortName "<新IP>"

做完务必再跑一次 doctor,确认第 3 层变成「可达」。
旧 IP 的端口会作为残留保留(无害);要清可用 Remove-PrinterPort。

装驱动本身走三层回退,适配 V4 打印驱动(当前 Xerox 包就是 V4 / PackageAware=TRUE):

  1. Add-PrinterDriver -Name <名> -InfPath <inf> ← V4 驱动首选
  2. pnputil /add-driver <inf> /install ← 老驱动包 / 旧系统
  3. Add-PrinterDriver -Name <名> ← 驱动已在库中时按名注册
  • 打印机解析顺序:--printer、环境变量 PRINTER_NAME、config.json、Windows 默认打印机。
  • --fit 只把超过可打印区域的页面缩小到纸张内,不会把多页文档合并成一页。
  • --dry-run 只验证文件、格式和打印机,不提交任务。
  • print 默认先做前三层预检(驱动 → WiFi → 连通性)。不合格直接中止并说明断在哪层,不会让任务悄悄卡在队列里。--no-precheck 可跳过。
  • 支持 PDF、png/jpg/jpeg/tif/tiff/bmp、docx、xlsx/xls。
  • Word/Excel 优先使用本机 Microsoft Office 转换为 PDF;没有 Office 时尝试 LibreOffice。

色彩策略:默认黑白,彩色需二次确认

两条规则,缺一不可:

规则 实现
默认走黑白,且默认机就是硬件黑白机 config.json 的 printer_name = 17F黑白打印机(.244,设备本身不支持彩色)
彩色必须二次确认 启动器要求 --color 与 --confirm-color 同时出现

调用方(Agent)该怎么做

  1. 用户没提配色 → 直接打印,不要追问。默认就是黑白,且走的是硬件黑白机。
  2. 用户明确要彩色("打彩色的"、"这个要彩印")→ 不要立刻提交,先复述确认一次
    (例如「确认要打彩色吗?彩色耗材更贵」),拿到肯定答复后才提交:

print --file "..." --printer 17F打印机 --color --confirm-color

彩色只能走 17F打印机(.243,唯一支持彩色的那台)。
3. 只传 --color 不传 --confirm-color → 启动器以 COLOR_NEEDS_CONFIRMATION
(退出码 46)拒绝执行并给出提示。这是刻意的:只认一个参数挡不住两类误判
——「把用户的模糊表述当成要彩色」和「顺手加 --color」,而那会静默出彩页。

想要的效果 怎么调
默认黑白(当前) 不传任何配色参数
打彩色 --color --confirm-color,且 --printer 17F打印机
临时改默认 环境变量 PRINTER_MONOCHROME=0(同样会被二次确认拦住)
永久改默认 config.json 的 print_monochrome_default 改成 false(同样要确认)

为什么这个开关做在启动器(bootstrap.ps1)而不是后端?
后端是远程预编译的 exe(runtime.url 指向的包,带 SHA-256 校验),
改它的源码不会生效。而启动器负责拼参数 —— 在这里补 --monochrome、加色彩闸门即可,
无需重新构建/发布运行组件,也不需要改 print_tool.py。
优先级:环境变量 PRINTER_MONOCHROME > config.json > 默认 false。

--color 为什么必须由启动器「剥掉」而不是传给后端?
因为后端(SumatraPDF)的 -print-settings 只认 monochrome,没有 color token
(已实测其二进制内的取值表)。也就是说一旦注入了黑白,就没有任何办法在同一队列上
强制彩色
。所以启动器把 --color / --confirm-color 一起吃掉(不让后端看到,
否则会报未识别参数),用「不注入」来得到彩色。这也意味着一件事:如果同时在
Windows 驱动层把该打印机的默认配色设为单色(见下),--color 就会失效。

> ⚠️ 默认机是硬件黑白机,所以哪怕闸门被绕过、往默认队列提交了彩色任务,
> 出来的仍然是黑白页 —— 这是刻意的第二层保险。

⚠️ 「默认黑白」的两个层次,别混

层次 手段 影响范围 彩色出口
本 skill(已启用) print_monochrome_default → 启动器注入 --monochrome + 色彩闸门 只影响经本 skill 提交的任务 ✅ --color --confirm-color
Windows 驱动默认 Set-PrintConfiguration -PrinterName "17F黑白打印机" -Color $false 本机所有程序打这台机器都变黑白(含 Word、浏览器) ❌ 只能改回来

驱动层那条需管理员权限,且会吃掉 --color(Sumatra 无 color token)。
默认机本身就是黑白机,没必要动它。查看当前驱动默认配色:

Get-PrintConfiguration -PrinterName "17F黑白打印机"   # 关注 Color 字段

doctor:四层环境体检

打印失败时,最怕「不知道断在哪」。doctor 从近到远逐层排查:

层 检查内容 失败含义
1 驱动与打印机安装 本机没装这台打印机,或装着的驱动与配置要求的不一致 → 需 install-driver
2 WiFi 网络环境 没连到要求的 wsdsocial
3 打印机连通性 TCP 探测打印机 IP(默认 9100,回退 515/631/445),失败再 ping 区分「不可达」与「端口被拦」
4 打印机状态 缺纸/卡纸/墨粉/脱机等

第 1 层会同时校验驱动名:打印机对象在、但驱动不是 config.json 里 driver_model
指定的那个,同样判 FAIL(这是「换了驱动包但没生效」的典型症状 —— 只看打印机在不在会漏掉它)。

--auto 会在第 1 层失败时自动安装/切换驱动(需管理员权限)。
第 2 层不会自动切换网络——只提示并停下,等用户确认(切网会短暂中断本机网络)。

data.fix_instructions 里给出每层的修复建议,可直接转述给用户。

给不用 WorkBuddy 的同事:一键安装脚本

SkillHub 技能包不允许 .bat 文件(平台安全策略),所以一键安装脚本单独分发:

https://share.wsdbrand.com/doc/viewer?id=R52p8WYJItzOf5Oj

下载解压后得到三个文件,双击 bat 即可完成「下载驱动 → 装驱动 → 建端口 →
建打印机 → 设默认」全流程,不需要 Python、不需要 WorkBuddy:

一键安装打印机驱动.bat        ← 双击这个
lan-print-install.ps1         ← 必须与 bat 同目录(bat 会调用它)
使用说明.txt                  ← 给人看的,非必需

前两个缺一不可(第三个只是说明)。之所以不做成单个 bat:bat 单行长度上限 8191 字符,
装不下完整逻辑,硬塞会把脚本变成不可维护的拼接。

bat 会自动请求管理员权限(UAC 弹窗点「是」)。参数与 config.json 一致,
换驱动或换 IP 时两处都要改:

变量 应为
$PrinterName 17F打印机
$PrinterIp 10.20.0.243
$DriverModel Xerox Global Print Driver PS
$DriverInfName x3UNIVP.inf
$ShareId si7P5ObInbUGUx5D

> ✅ 2026-09-22 已修复并换新条目:$PrinterIp 已改为现网可达的 10.20.0.243,
> 重新发布为 OA 条目 lan-print-oneclick-install-v3(即本页上方那个链接),并做了下载回验:
> 线上文件 SHA-256 与本地构建产物字节级一致、包内 ps1 确认写的是 10.20.0.243。
> 此前两个旧条目 —— lan-print-oneclick-install(包内 ps1 仅 9,599 字节那版)与
> lan-print-oneclick-install-v2 —— 经实测确实写死 10.20.0.246,
> 不要再分发,建议在 OA 里删除以免混淆。
>
> 📌 改 IP / 换驱动时的分发纪律:ps1 里的 $PrinterIp 与 config.json 是两处独立副本,
> 必须同时改;且 OA 不支持覆盖已发布文件,只能新建条目。

> ⚠️ 编码约束:bat 用 GBK 存中文(cmd 默认代码页 936),ps1 用 UTF-8 带 BOM
> 存(PowerShell 5.1 读无 BOM 的 UTF-8 会按 GBK 解析,中文注释会破坏语法)。
> 改动这两个文件时务必保持编码,否则会出现「乱码」或「脚本静默退出」。

🔴 已知坑:xlsx 打印「内容不完整」(2026-09-22 定位并修复)

症状:print --file xxx.xlsx 报成功、队列也清空,但纸张上内容只出来一部分
(右侧/下方被切掉),看着像「没打全」。

根因:本机 Excel + Xerox GPD PS 驱动下,ExportAsFixedFormat 在页面缩放 < 100%
时,写出的 PDF 页面尺寸 = 纸张 ÷ 缩放比例:

PageSetup.Zoom 导出 PDF 的 MediaBox 说明
100 842.04 × 594.96 pt ✅ 真 A4 横版,唯一正确的一档
90 935.60 × 661.07 pt = A4 ÷ 0.9
57(fit-to-page 自动算出的) 1477.26 × 1043.79 pt = A4 ÷ 0.57

也就是说:本该「把内容缩到 A4 里」,实际变成「把纸放大了」。页面被撑到 521×368 mm
后,打印机侧按 100% 输出,超出物理 A4 的部分静默裁掉 —— 这就是内容缺失。
PrintScale = shrink 兜不住,因为驱动上报的可打印区域同样是那个被放大的尺寸,判定为「无需缩小」。

排查要点(已证伪的假设,别重复走):
- 不是台账文件的问题:新建空白工作簿 + Zoom=90 同样复现。
- 不是内嵌 printerSettings1.bin:删掉它、删掉 pageSetup 的 r:id、补 fitToWidth/Height,导出尺寸一模一样。
- 不是驱动谎报纸张:PrinterSettings.PaperSizes 里 A4 就是 210×297 mm。
- 不是 --fit 的锅:--fit 只加 Sumatra 的 shrink,改不了 PDF 自身页面尺寸。
- 唯一变量是缩放档位:这是目前已知唯一的触发条件。

判定与处置:导出后检查 PDF 的 MediaBox。
- 若宽 ≈ 842(A4 横版)→ 正常,直接打。
- 若宽明显 > 842(A4 比例)→ 必须归一化:把页面连同内容整体缩 842.04 / 页面宽,
正好等于 Excel 内部那个缩放比例(1477.26 → 842.04 即 0.5699)。
已实现为 print_tool.py 的 normalize_pdf_page_size(),在 convert_xlsx_with_excel()
导出后自动调用(非 A4 比例如 A3/Letter 不擅自改;已是 A4 则原样放行)。

> ✅ 已修复并上线(2026-09-22):运行组件已重建为 v5,config.json 的
> runtime.file_name/url/sha256 已指向 v5,构建环境已加 pypdf(用到
> PageObject.add_transformation)。新装或已装的用户下次运行会自动拉取 v5。
>
> ⚠️ 为什么必须重建 exe:bootstrap.ps1 跑的是打包好的
> lan-print-runtime-windows-x64-vN.exe(不是本目录的 print_tool.py)——
> 只改源码不同步 exe,客户端行为完全不变。
>
> ⚠️ 陷阱:归一化失败是静默的。normalize_pdf_page_size() 在 import pypdf
> 失败时只返回一段告警、不抛异常(设计如此:不让 pypdf 缺失阻断打印)。
> 因此如果 pypdf 没被打进 exe,现象是悄悄跳过归一化、原 bug 照旧复现,极难发现。
> 重建后必须实测冻结环境下 pypdf 可用(v5 已用同配置探针 exe 实测:
> pypdf_import = OK,1477×1044 pt → 841.89×595.28 pt)。
>
> 旧版(v4 及更早)用户的应急做法:先在 Excel 里导出 PDF(会得到同样被撑大的页面),
> 按 842.04 / 页面宽 把页面连同内容缩回真 A4,再把修正后的 PDF 交给 print
> (PDF 走原样打印、不做任何转换,因此不会再被撑大)。只导出、不归一化就交给
> print,等于把问题原样复现一遍。

🔴 已知坑:宿主「安全删除」包装 + StrictMode = 下载装不上(2026-09-22 定位并修复)

症状:首次运行(或换版本后)需要下载运行组件时,下载明明完成、却报装不上;
stdout / --out-file 的 JSON 全是空的,只在 stderr 里看到一句莫名其妙:

Remove-Item: &lt;skill_dir&gt;\bootstrap.ps1:33x
  | Remove-Item -LiteralPath $extractDir -Recurse -Force -ErrorAc …
  | 无法检索变量 &#x27;$LASTEXITCODE&#x27;,因为尚未设置该变量。

根因:宿主环境(WorkBuddy / CodeBuddy)会把 Remove-Item 替换成一个全局函数
「安全删除包装」(内部引用 $env:CODEBUDDY_SAFE_DELETE_TRASH_BIN /
$env:GENIE_TRASH_DIR,把目标送回收站而不是真删)。该包装内部有一句
$exitCode = $LASTEXITCODE;而 bootstrap.ps1 开了 Set-StrictMode -Version Latest,
在还没跑过任何原生程序时 $LASTEXITCODE 是「未定义变量」→ 读取即抛
VariableIsUndefined → 整个 Remove-Item 失败 → 解压临时目录清理崩掉 → 安装中止。

它是怎么被触发的:Install-Asset 发现缓存里没有目标版本 → 走下载分支 →
Expand-DownloadedPackage 的 finally 里 Remove-Item $extractDir 撞上包装。
(缓存已命中时 Install-Asset 直接 return,不碰这条路径 —— 所以「以前能跑」不代表没问题,
只有真正发生版本升级时才暴露。)

已做的两处修复(都在 bootstrap.ps1):

# 修复 说明
1 紧接 Set-StrictMode 之后加 $global:LASTEXITCODE = 0 让任何宿主包装读 $LASTEXITCODE 都能拿到确定值(该脚本尾部原本就为同一原因做过一次,现在提前到最前)
2 新增 Remove-ScratchPath(),用 [System.IO.Directory/File]::Delete 替换全部 3 处 Remove-Item ① 不做命令解析,天然绕开宿主包装;② 我们的 extract-* / pkg-* 是纯中间产物,不该被送进回收站;③ 宿主包装收到多个路径时会拼成一个字符串再 Resolve-Path → PathNotFound

排查要点(供后续复用):
- 症状像「网络/分发渠道坏了」,实际是本地宿主包装与脚本 StrictMode 的组合问题,
换渠道、换链接都无济于事。
- 拿不到 stdout 时用包装脚本 + 打印 $Error 栈定位:$Error[0].ScriptStackTrace
会直接点出被劫持的 global:Remove-Item 与内部行号 —— 比看日志快得多。
- 判断宿主是否劫持了命令:Get-Command Remove-Item -All 若第一行 CommandType=Function,即为被接管。
- 清理失败会留下实打实的垃圾:每失败一次残留一个 22 MB .download + 一个
extract-* 目录 + 一个 pkg-*.exe。修好后务必去
%LOCALAPPDATA%\WorkBuddy\lan-print\runtime-v1\ 手工清一次。

> 注:一键安装脚本 lan-print-install.ps1 没有开 StrictMode,且同事是双击 bat
> 在普通 PowerShell 里跑(没有宿主包装),因此不受此问题影响,无需修改。

操作规则

> ### 🚧 硬门禁:任何打印请求的第一步必须是 doctor
>
> 任何打印请求的第一件事,必须先运行 doctor 确认四层环境;首轮对话不跳过此步。
>
> - 顺序固定:先 doctor → 后 print。不允许直接跳到 print。
> - 四层中有任何一层 FAIL,先停下来把断点告诉用户并给修复建议,
> 不要提交打印任务(print 自身的前三层预检也会拦截,但那只是兜底,不能替代 doctor)。
> - 不得以下列理由跳过:用户催得急、文件很简单、刚才刚打印成功过、
> 或者「上次已经体检过了」。环境(网络 / 打印机状态)随时可能变。
> - 唯一的例外:用户明确表示只要体检结果、不要打印 —— 那 doctor 本身就是终点。
>
> 这条门禁的意义在于:打印任务一旦提交到队列,失败往往是静默的
> (任务卡在队列里、纸张没出来),事后排查成本远高于事先 10 秒的体检。

  • 用户明确指定文件、打印机和份数时,可直接打印;未指定打印机时使用配置里的目标,并在结果中告知实际目标。
  • 打印默认黑白(print_monochrome_default: true + 默认机是硬件黑白机)。用户没提配色
    就直接打,不要追问;用户明确要彩色时,必须先复述确认一次,得到肯定答复后再用
    --printer 17F打印机 --color --confirm-color —— 只给 --color 会被启动器以
    COLOR_NEEDS_CONFIRMATION(退出码 46)拦下,别绕、也别去改 config.json。
  • 提交后用 --dry-run 的返回或结果里的 monochrome 字段可以确认本次是不是黑白。
  • 用户只是询问“怎么打印”或表达意图不明确时,不要提交任务,可先使用 --dry-run。
  • 取消单个任务前可先运行 status 获取任务 ID。
  • “取消任务”不能推断为取消全部;只有用户明确要求清空该打印机队列时才使用 cancel --all。
  • --copies 最大为 20。不要通过循环多次调用来绕过限制。
  • 成功只表示任务已提交到 Windows 打印队列,不代表纸张已经输出;离线、缺纸或卡纸可能在提交后才出现。
  • 安装驱动需要管理员权限。非管理员时脚本会明确说明并给替代路径,不会假装成功。若驱动包只有交互式 setup.exe(无 .inf),会识别并提示手工双击。

输出

  • 退出码 0:成功,JSON 输出到 stdout。
  • 非零退出码:失败,JSON 错误输出到 stderr。
  • 向用户转述 message;需要进一步操作时,可读取 data 中的打印机名、任务 ID 和状态。
  • 常见错误码:PRECHECK_DRIVER_FAILED(70) / PRECHECK_WIFI_FAILED(71) / PRECHECK_UNREACHABLE(72) 表示打印前预检未过;DRIVER_ADMIN_REQUIRED(63) 表示需提权;DRIVER_INSTALL_FAILED(66) 多为 driver_model 与驱动库显示名不一致;SUBNET_INVALID(68) 是 discover --subnet 传了非法网段。
  • WECOM_CLI_*、WECOM_AUTH_REQUIRED 或 DOWNLOAD_* 表示首次下载条件未满足;修复后直接重试即可。

常见问题

5 问
答案由本站依据条目字段整理
局域网打印助手怎么安装?

在支持 Skills 的客户端里执行:skillhub install user_f43c4493/wsd20260901。安装方式为未标注。装完刷新技能列表或重开客户端。

局域网打印助手支持哪些客户端?

资料没有标注宿主客户端,但只要客户端支持 Skills(Claude、Codex、Cursor 等),一般都能加载。

局域网打印助手权限高吗,安全吗?

权限级别为未标注权限。安装前先看它会读取或写入哪些内容。

局域网打印助手收费吗?

本站不代收费用,也没有标注具体价格。是否收费取决于技能本身和所用的模型或客户端,正式使用前按作者说明确认。

局域网打印助手用什么许可证?

许可证标注为 未说明(许可证不明确)。商用或二次分发前请到仓库确认条款原文。

热门专题

按场景挑技能
全部专题 →

技能内容以作者仓库为准;分类、权限级别与许可证状态的中文说明为中文整理,最近核验 2026-11-06。