rs-printer-utils
v0.2.0
Published
使用 Rust、napi-rs 和 windows-rs 读写 Windows 打印机驱动设置
Maintainers
Readme
rs-printer-utils
一个仅适用于 Windows 的 Node.js 原生扩展。它使用 Rust、napi-rs 和 windows-rs,读取或修改 Windows 打印机驱动的默认 DEVMODE 设置。
- npm:rs-printer-utils
- GitHub:kuigoo/rs-printer-utils
功能
- 列出本机安装的打印机和当前用户连接的网络打印机。
- 读取方向、份数、彩色、双面、纸张编号、纸张宽高、纸盒和分辨率等设置。
- 只修改传入的字段,未传入的设置保持不变。
- 用毫米设置驱动支持的自定义纸张宽度和高度。
- 修改前交给打印机驱动校验,并返回驱动最终接受的值。
- 读取 Windows 打印队列状态,并解析脱机、缺纸、卡纸等状态位。
- 异步探测 USB 或标准 TCP/IP 打印机与本机的连接情况。
- 提供 TypeScript 类型声明。
环境要求
- Windows x64
- Node.js 18 或更高版本
- 从源码构建时,需要 Rust MSVC 工具链、Node.js 22.13 或更高版本,以及 pnpm 或 npm
当前 npm 包提供 Windows x64 预编译文件,不能在 Windows ARM64、macOS 或 Linux 上安装和加载。
安装
npm install rs-printer-utils也可以使用 pnpm 或 yarn:
pnpm add rs-printer-utils
# 或
yarn add rs-printer-utils从源码构建:
pnpm install
pnpm run build发布包已经包含 .node 原生文件,普通使用者不需要安装 Rust 或 Visual Studio Build Tools。
快速开始
const {
listPrinters,
getPrinterSettings,
getPrinterStatus,
probePrinterConnection,
setPrinterSettings,
setCustomPaperSize,
} = require('rs-printer-utils')
const printers = listPrinters()
console.log(printers)
const printerName = printers[0].name
console.log(getPrinterSettings(printerName))
console.log(getPrinterStatus(printerName))
probePrinterConnection(printerName, { timeoutMs: 2000 })
.then(console.log)
.catch(console.error)
// 只修改方向、份数和彩色设置。
const updated = setPrinterSettings(printerName, {
orientation: 'landscape',
copies: 2,
color: 'monochrome',
})
console.log(updated)
// 设置 100 mm × 150 mm 自定义纸张。
const custom = setCustomPaperSize(printerName, 100, 150)
console.log(custom)API
listPrinters()
列出本地打印机和当前用户已连接的网络打印机。
interface PrinterInfo {
name: string
serverName?: string
attributes: number
}getPrinterSettings(printerName)
读取打印机当前的默认驱动设置。驱动没有声明使用的字段会被省略;supportedFields 表示当前 DEVMODE.dmFields 中存在的字段,不表示某个字段的所有值都一定受支持。
const settings = getPrinterSettings('Microsoft Print to PDF')返回值可能包含:
| 字段 | 说明 |
| --- | --- |
| deviceName | 驱动设备名 |
| orientation | portrait、landscape 或 unknown |
| copies | 默认份数 |
| color | monochrome、color 或 unknown |
| duplex | simplex、longEdge、shortEdge 或 unknown |
| paperSize | Windows DMPAPER_* 数值 |
| paperWidthMm | 纸张宽度,单位为毫米 |
| paperHeightMm | 纸张高度,单位为毫米 |
| defaultSource | 默认纸盒编号 |
| printQuality | 打印质量或横向 DPI |
| yResolution | 纵向 DPI |
| supportedFields | 驱动在 dmFields 中声明的字段名 |
getPrinterStatus(printerName)
同步读取 Windows 打印队列报告的状态。它适合判断队列是否报告为脱机,但不能单独证明物理打印机已经连接。
Reads the status reported by the Windows print queue. It can show an offline queue, but it does not prove that the physical printer is connected.
const status = getPrinterStatus('Office Printer')
console.log(status.isOffline, status.statusFlags)interface PrinterStatus {
printerName: string
statusCode: number
statusFlags: string[]
isOffline: boolean
isNotAvailable: boolean
isUnknown: boolean
}当 statusCode 为 0 时,statusFlags 返回 ['ready']。这里的 ready 只表示打印后台处理程序没有报告错误;部分驱动在设备断开时仍可能返回 0。
probePrinterConnection(printerName, options?)
异步探测打印机从本机是否可达,默认超时为 2000 毫秒,可设置范围为 100 到 30000 毫秒。网络连接在 napi-rs 工作线程中执行,不会在等待 TCP 超时时阻塞 Node.js 主线程。
Checks whether the printer can be reached from this PC. The default timeout is 2000 ms. The TCP check runs outside the Node.js main thread.
async function checkConnection() {
const connection = await probePrinterConnection('Office Printer', {
timeoutMs: 1500,
})
console.log(connection.connectionType, connection.state)
}
checkConnection().catch(console.error)interface PrinterConnection {
printerName: string
connectionType: 'usb' | 'tcpIp' | 'shared' | 'wsd' | 'virtual' | 'unknown'
state: 'connected' | 'disconnected' | 'unknown' | 'notApplicable'
method: 'pnp' | 'tcp' | 'spooler'
portName?: string
endpoint?: string
statusCode: number
statusFlags: string[]
details?: string
}不同连接类型的处理方式如下:
| connectionType | 探测方式 | 可能结果 |
| --- | --- | --- |
| usb | 仅在队列提供明确的 USBPRINT 设备实例 ID 时查询 Windows 即插即用设备节点;缺少可靠映射时不猜测 | connected、disconnected 或 unknown |
| tcpIp | 读取标准 TCP/IP 端口的主机和端口,再执行带超时的 TCP 连接 | connected、disconnected 或 unknown |
| shared | 客户端无法确认打印服务器后面的物理设备 | unknown |
| wsd | WSD 发现信息可能来自缓存,当前版本不作物理连接结论 | unknown |
| virtual | FILE:、PORTPROMPT:、NUL:、传真等没有物理端点的队列 | notApplicable |
| unknown | 端口类型或多端口组合无法安全识别 | unknown |
connected 表示 USB 设备节点已存在并正常启动,或配置的 TCP 端口接受了连接。它只表示当前可达,不保证纸张、耗材、驱动和打印任务都正常。disconnected 只在有明确证据时返回;无法建立可靠映射时返回 unknown,避免误报。
如果 Windows 无法提供标准 TCP/IP 端口的真实配置,本包可以用端口名中的 IP 尝试默认的 9100 端口;连接成功可返回 connected,但连接失败仍返回 unknown,因为实际队列可能使用 LPR 515 或自定义端口。
If Windows cannot provide the real TCP/IP port settings, a failed check on port 9100 stays unknown because the queue may use LPR 515 or a custom port.
connected means that a USB device node is present and started, or a TCP port accepted a connection. It shows reachability, not full print readiness. If the result is not clear, the API returns unknown.
setPrinterSettings(printerName, patch)
按补丁方式修改当前用户的打印机默认设置。可传字段如下:
interface PrinterSettingsPatch {
orientation?: 'portrait' | 'landscape'
copies?: number
color?: 'monochrome' | 'color'
duplex?: 'simplex' | 'longEdge' | 'shortEdge'
paperSize?: number
paperWidthMm?: number
paperHeightMm?: number
defaultSource?: number
}paperWidthMm 和 paperHeightMm 必须一起传入,范围为 0.1 到 3276.7 毫米。自定义宽高不能和 paperSize 同时传入。
此方法先读取包含驱动私有数据的完整 DEVMODE,合并公开字段,再调用 DocumentPropertiesW 让驱动校验,最后通过 SetPrinterW 的 PRINTER_INFO_9 保存为当前用户默认值。
setCustomPaperSize(printerName, widthMm, heightMm)
设置自定义纸张的便捷方法,等价于同时传入 paperWidthMm 和 paperHeightMm:
setCustomPaperSize('4BARCODE 4B-3044B', 80, 50)Windows 在 DEVMODE 中以 0.1 毫米为单位保存尺寸,本包会自动换算并四舍五入。
可直接运行的示例
项目的 examples/set-custom-paper-size.js 可以直接通过 Node.js 运行。先查看可用打印机:
node examples/set-custom-paper-size.js --list再传入打印机名称、纸张宽度和纸张高度:
node examples/set-custom-paper-size.js "4BARCODE 4B-3044B" 100 150宽度和高度的单位都是毫米。脚本会先输出原设置,随后写入自定义纸张大小,并打印驱动最终接受的设置。此命令会真实修改打印机的当前用户默认设置。
注意事项
- 驱动可以调整或拒绝设置。请使用方法的返回值确认驱动最终接受的配置。
- 自定义纸张是否可用取决于打印机驱动。有些驱动要求先在“打印服务器属性”中创建纸张规格,本包不会创建或删除系统级纸张规格。
- 写入设置需要打印机管理权限。权限不足时,
OpenPrinterW或SetPrinterW会返回错误。 - 除
probePrinterConnection外,其余 API 都是同步方法。访问远程打印机时,Windows 打印后台处理程序可能阻塞较长时间,请不要在对响应时间敏感的主线程中频繁调用。 - 队列脱机状态和物理连接状态是两个不同信号。建议分别读取
getPrinterStatus和probePrinterConnection,不要把statusFlags: ['ready']直接解释为设备在线。 setPrinterSettings修改当前用户默认值,不会更改系统默认打印机,也不会修改已经进入队列的打印任务。
开发
pnpm run check
pnpm run build:debug
pnpm testRust 代码会保留驱动附加在 DEVMODE 后面的私有数据,避免只传公开结构而导致驱动校验失败。
许可证
MIT
