尧图精选

Electron PrinterInfo 对象详解:通过 getPrintersAsync 获取与解析系统打印机列表

🕒 发布时间:2026/9/7 23:08:46 📁 来源:尧图网络
Electron PrinterInfo 对象详解通过 getPrintersAsync 获取与解析系统打印机列表【免费下载链接】electron:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS项目地址: https://gitcode.com/GitHub_Trending/el/electron在 Electron 中构建“打印到指定设备”“打印机状态监控”或“打印设置面板”类功能时核心数据结构就是PrinterInfo对象。它由webContents.getPrintersAsync()返回封装了操作系统认识的打印机名称、打印预览中显示的名称、设备描述以及一大块平台相关的options键值对。读完本文你将掌握PrinterInfo各字段的准确语义、各平台Windows / Linux / macOS下options与状态码的差异、以及 Electron 从 JS 层到 Chromium 打印后端的完整实现链路能直接在自己的应用中落地打印机枚举与选择逻辑。PrinterInfo 对象结构PrinterInfo是一个纯数据对象共 4 个字段字段类型说明namestring操作系统层面识别的打印机名称system-defined namedisplayNamestring在打印预览Print Preview中展示的打印机名称descriptionstring对打印机类型的更长描述例如机型信息optionsObject包含数量不定的、平台相关的打印机信息键值对name与displayName的区别是使用中最容易踩坑的一点name是操作系统内部名称通常是带下划线、无空格的机器标识displayName才是给用户看的友好名称。当你调用webContents.print({ deviceName })指定打印设备时传入的必须是name系统定义名而不是displayNamefriendly name。这一约束在官方文档的contents.print()一节中同样有强调deviceNamestring (optional) - Set the printer device name to use. Must be the system-defined name and not the friendly name, e.gBrother_QL_820NWBand notBrother QL-820NWB.options 字段平台相关的扩展信息options是PrinterInfo中信息量最大的部分其键值数量和内容因平台而异。官方示例如下展示了一台 Linux/CUPS 环境下网络打印机的典型输出{ name: Austin_4th_Floor_Printer___C02XK13BJHD4, displayName: Austin 4th Floor Printer C02XK13BJHD4, description: TOSHIBA ColorMFP, options: { copies: 1, device-uri: dnssd://Austin%204th%20Floor%20Printer%20%40%20C02XK13BJHD4._ipps._tcp.local./?uuid71687f1e-1147-3274-6674-22de61b110bd, finishings: 3, job-cancel-after: 10800, job-hold-until: no-hold, job-priority: 50, job-sheets: none,none, marker-change-time: 0, number-up: 1, printer-commands: ReportLevels,PrintSelfTestPage,com.toshiba.ColourProfiles.update,com.toshiba.EFiling.update,com.toshiba.EFiling.checkPassword, printer-info: Austin 4th Floor Printer C02XK13BJHD4, printer-is-accepting-jobs: true, printer-is-shared: false, printer-is-temporary: false, printer-location: , printer-make-and-model: TOSHIBA ColorMFP, printer-state: 3, printer-state-change-time: 1573472937, printer-state-reasons: offline-report,com.toshiba.snmp.failed, printer-type: 10531038, printer-uri-supported: ipp://localhost/printers/Austin_4th_Floor_Printer___C02XK13BJHD4, system_driverinfo: T } }从这份示例可以提炼出几个跨平台开发时需要知道的要点所有值都是字符串。即使是布尔语义printer-is-accepting-jobs: true或数值语义job-priority: 50、printer-state: 3也保持字符串形态使用前必须自行转换。CUPS 语义的键名。在 Linux/macOS 上options中大量出现device-uri、job-cancel-after、printer-state-reasons、printer-make-and-model这类 IPP/CUPS 标准属性名说明该平台的打印机属性直接透传自 CUPS 服务。状态值含义随平台变化。示例中的printer-state: 3在 CUPS 语义里表示空闲但离线idle, but offline配合printer-state-reasons: offline-report,...可以进一步判断不可打印的原因。官方文档明确提示这些数字在不同平台含义不同——Windows 上的取值含义对应 Win32 打印 API 的打印机信息结构定义Linux 与 macOS 上的取值含义则遵循 CUPS 打印机监控接口的规范。因此跨平台代码不应硬编码状态数字而应按平台分支处理。厂商私有属性也可能出现。示例中的com.toshiba.ColourProfiles.update等printer-commands内容是厂商私有的 IPP 扩展命令说明options是可变键的开放容器代码中应按需取用、容错缺省而不是假设固定键集合。获取方式webContents.getPrintersAsync()获取PrinterInfo[]的入口是webContents.getPrintersAsync()contents.getPrintersAsync() // Returns PromisePrinterInfo[] - Resolves with a PrinterInfo[]该方法位于 web-contents.md 文档中返回一个解析为PrinterInfo[]的 Promise。一个典型的列出并选择打印机用法如下const { BrowserWindow } require(electron) async function pickPrinter() { const win new BrowserWindow({ width: 800, height: 600 }) await win.loadURL(about:blank) const printers await win.webContents.getPrintersAsync() // name 用于 print() 的 deviceNamedisplayName 用于展示给用户 console.table(printers.map((p) ({ name: p.name, displayName: p.displayName, state: p.options[printer-state] ?? N/A }))) // 静默打印到指定系统打印机deviceName 必须是 name而非 displayName win.webContents.print({ silent: true, deviceName: printers[0].name }, (success) console.log(print success:, success)) }这里有一个值得注意的历史演进早期的webContents.getPrinters()同步方法已被废弃并最终移除迁移方式在 breaking-changes.md 中有明确记载// 旧写法已移除 console.log(w.webContents.getPrinters()) // 新写法 w.webContents.getPrintersAsync().then((printers) { console.log(printers) })因此在当前仓库对应的版本中枚举打印机应一律使用异步版本。源码实现链路从 JS Promise 到 Chromium 打印后端结合仓库源码getPrintersAsync()的完整调用链可以分为三层第一层JS 包装层。lib/browser/api/web-contents.ts 中WebContents.prototype.getPrintersAsync直接委托给内部 native bindingprinting.getPrinterListAsync()WebContents.prototype.getPrintersAsync async function () { // TODO(nornagon): this API has nothing to do with WebContents and should be // moved. if (printing.getPrinterListAsync) { return printing.getPrinterListAsync() } else { console.error(Error: Printing feature is disabled.) return [] } }从源码结构看这一层还揭示了一个重要前提整个打印功能受ENABLE_PRINTING构建开关控制。当 Electron 以禁用打印的方式构建时printing.getPrinterListAsync不存在getPrintersAsync()会打印Error: Printing feature is disabled.并返回空数组——这解释了为什么某些 Electron 构建尤其是部分 Linux 打包场景下打印机列表为空。第二层Native 异步枚举层。shell/browser/api/electron_api_printing.cc 中的GetPrinterListAsync是该 API 的核心实现v8::Localv8::Promise GetPrinterListAsync(v8::Isolate* isolate) { gin_helper::Promiseprinting::PrinterList promise(isolate); v8::Localv8::Promise handle promise.GetHandle(); base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()}, base::BindOnce([]() { printing::PrinterList printers; auto print_backend printing::PrintBackend::CreateInstance( g_browser_process-GetApplicationLocale()); printing::mojom::ResultCode code print_backend-EnumeratePrinters(printers); if (code ! printing::mojom::ResultCode::kSuccess) LOG(INFO) Failed to enumerate printers; return printers; }), base::BindOnce( [](gin_helper::Promiseprinting::PrinterList promise, const printing::PrinterList printers) { promise.Resolve(printers); }, std::move(promise))); return handle; }这段代码解释了 API 异步语义的由来打印机枚举涉及与系统打印服务Windows 的 spooler、CUPS 守护进程等的交互可能阻塞因此被投递到线程池中执行USER_VISIBLE优先级、MayBlock属性完成后在主线程 resolve Promise。同时可以看到枚举直接复用 Chromium 的printing::PrintBackend按浏览器进程 locale 创建实例并调用EnumeratePrinters——这也是为什么 Linux/macOS 上options会呈现 CUPS/IPP 属性名平台差异发生在 Chromium 的打印后端内部Electron 只负责透传。第三层结构体到 JS 对象的映射。同文件中注册了printing::PrinterBasicInfo的 gin Converter逐字段映射出PrinterInfo对象template struct Converterprinting::PrinterBasicInfo { static v8::Localv8::Value ToV8(v8::Isolate* isolate, const printing::PrinterBasicInfo val) { auto dict gin_helper::Dictionary::CreateEmpty(isolate); dict.Set(name, val.printer_name); dict.Set(displayName, val.display_name); dict.Set(description, val.printer_description); dict.Set(options, val.options); return dict.GetHandle(); } };这四行dict.Set与文档中定义的 4 个字段一一对应options则整体取自PrinterBasicInfo的平台相关属性表。打印流程中的关联工具PrinterInfo不只是列表展示用途它还与打印执行路径紧密关联。shell/browser/printing/printing_utils.h 中定义了若干围绕打印机选择的工具函数从注释可以看出 Electron 对deviceName的健壮性处理IsDeviceNameValidChromium 本身不对device_name做有效性检查传入不存在的设备名会导致崩溃因此 Electron 会先校验GetDeviceNameToUse用户传了deviceName则校验后使用未传则优先取系统默认打印机没有默认打印机时退化为取列表中的第一台列表为空则失败——这正是getPrintersAsync()返回结果可直接用于兜底选择的原因GetPrinterDefaultPaperSize/GetDefaultPrinterDPI为print({ usePrinterDefaultPageSize: true })等选项提供具体打印机的默认纸张与 DPI。此外 shell/browser/printing/print_view_manager_electron.cc 接管了打印任务的生命周期打印开始、结束、取消等事件是webContents.print()回调机制的底层所在。测试验证仓库的规格测试印证了该 API 的行为契约。spec/api-web-contents-spec.ts 中ifdescribe(features.isPrintingEnabled())(getPrintersAsync(), () { afterEach(closeAllWindows); it(can get printer list, async () { const w new BrowserWindow({ show: false, webPreferences: { sandbox: true } }); await w.loadURL(about:blank); const printers await w.webContents.getPrintersAsync(); expect(printers).to.be.an(array); }); });两个细节值得注意测试块被features.isPrintingEnabled()条件包裹再次证明该 API 仅在启用了打印构建开关的环境下可用、可测测试断言返回类型是数组而非检查具体元素——由于打印机列表强依赖运行环境的实际硬件/驱动这是此类系统 API 合理的测试粒度。使用要点小结字段分工程序化选择打印机用name界面展示用displayName机型说明参考description平台差异options键集合与状态值语义因平台而异Windows 对应 Win32 打印 API 定义Linux/macOS 对应 CUPS 规范跨平台逻辑需按平台分支并容忍缺键值类型options内全部为字符串数值/布尔需自行解析构建前提功能受ENABLE_PRINTING编译开关保护禁用打印的构建中getPrintersAsync()会返回空数组并输出错误日志历史迁移同步版webContents.getPrinters()已移除统一使用getPrintersAsync()。掌握以上要点后你可以在 Electron 应用中可靠地枚举系统打印机、解析平台相关的打印机状态并将name正确接入webContents.print()的deviceName选项实现完整的程序化打印流程。【免费下载链接】electron:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS项目地址: https://gitcode.com/GitHub_Trending/el/electron创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →