You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Tauri应用中访问、控制本地打印机并追踪打印状态?

Tauri程序访问本地打印机的跨平台最优方案

针对你的需求,直接基于Rust封装跨平台打印逻辑是最优解——绕过功能受限的tauri-plugin-printer,直接调用各平台原生API实现完整的打印机管理、任务提交和状态追踪能力。以下是分平台的具体实现方案及Tauri整合方式:

核心能力实现

1. 获取打印机列表

Windows

使用windows crate调用Print Spooler API,示例代码片段:

use windows::Win32::Graphics::Printing::{EnumPrinters, PRINTER_ENUM_LOCAL, PRINTER_INFO_2W};
use windows::core::PCWSTR;

fn get_local_printers() -> Vec<String> {
    let mut printers = Vec::new();
    let mut buffer_size = 0;
    let mut printer_count = 0;

    // 先获取所需缓冲区大小
    unsafe {
        EnumPrinters(PRINTER_ENUM_LOCAL, PCWSTR::null(), 2, None, 0, &mut buffer_size, &mut printer_count);
    }

    let mut buffer = vec![0u8; buffer_size as usize];
    unsafe {
        EnumPrinters(PRINTER_ENUM_LOCAL, PCWSTR::null(), 2, Some(buffer.as_mut_ptr()), buffer_size, &mut buffer_size, &mut printer_count);
    }

    // 解析打印机信息
    let printer_info_array = unsafe { std::slice::from_raw_parts(buffer.as_ptr() as *const PRINTER_INFO_2W, printer_count as usize) };
    for info in printer_info_array {
        let name = unsafe { info.pPrinterName.to_string().unwrap() };
        printers.push(name);
    }

    printers
}

MacOS

基于CUPS底层机制,直接调用系统lpstat命令解析输出:

use std::process::Command;

fn get_local_printers() -> Vec<String> {
    let output = Command::new("lpstat")
        .arg("-a")
        .output()
        .expect("Failed to execute lpstat");
    
    let stdout = String::from_utf8(output.stdout).unwrap();
    stdout.lines()
        .map(|line| line.split_whitespace().next().unwrap().to_string())
        .collect()
}

Linux

使用cups-rs crate(CUPS的高层Rust封装)快速获取列表:

use cups::http::HttpConnection;
use cups::printer::Printer;

fn get_local_printers() -> Vec<String> {
    let conn = HttpConnection::new("localhost:631").unwrap();
    let printers = Printer::get_all(&conn).unwrap();
    printers.iter().map(|p| p.name.clone()).collect()
}

2. 提交PDF打印任务

Windows

调用系统默认打印接口快速实现,或用ghostscript做格式兼容处理:

use std::process::Command;

fn print_pdf(pdf_path: &str, printer_name: &str) -> Result<(), Box<dyn std::error::Error>> {
    Command::new("rundll32.exe")
        .args(&["printui.dll,PrintUIEntry", "/k", "/n", printer_name, pdf_path])
        .spawn()?;
    Ok(())
}

MacOS

通过lpr命令提交打印任务:

use std::process::Command;

fn print_pdf(pdf_path: &str, printer_name: &str) -> Result<(), Box<dyn std::error::Error>> {
    Command::new("lpr")
        .arg("-P")
        .arg(printer_name)
        .arg(pdf_path)
        .status()?;
    Ok(())
}

Linux

通过cups-rs提交作业并返回作业ID用于后续追踪:

use cups::http::HttpConnection;
use cups::job::Job;

fn print_pdf(pdf_path: &str, printer_name: &str) -> Result<u32, Box<dyn std::error::Error>> {
    let conn = HttpConnection::new("localhost:631").unwrap();
    let job_id = Job::print_file(&conn, printer_name, pdf_path, "Tauri Print Job", &[])?;
    Ok(job_id)
}

3. 打印状态追踪

Windows

通过windows crate定期调用GetJob API查询指定作业状态,或监听Print Spooler的事件通知。

MacOS/Linux

借助CUPS API或系统命令查询作业状态:

// Linux示例,MacOS可通过`lpstat -j <job_id>`解析输出
use cups::http::HttpConnection;
use cups::job::Job;

fn get_job_status(job_id: u32) -> String {
    let conn = HttpConnection::new("localhost:631").unwrap();
    let job = Job::get(&conn, job_id).unwrap();
    job.state.to_string()
}

Tauri整合方式

将Rust逻辑封装为Tauri命令,供前端调用:

#[tauri::command]
fn get_printers() -> Vec<String> {
    #[cfg(target_os = "windows")]
    return get_local_printers();
    #[cfg(target_os = "macos")]
    return get_local_printers();
    #[cfg(target_os = "linux")]
    return get_local_printers();
}

#[tauri::command]
fn print_pdf_task(pdf_path: String, printer_name: String) -> Result<u32, String> {
    match print_pdf(&pdf_path, &printer_name) {
        Ok(job_id) => Ok(job_id),
        Err(e) => Err(e.to_string()),
    }
}

// 注册命令到Tauri应用
fn main() {
    tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![get_printers, print_pdf_task])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

打印店场景适配建议

  • 本地缓存已支付订单:避免网络波动导致重复打印,完成后同步状态到数据库
  • 任务队列机制:多订单排队打印,避免打印机阻塞
  • 失败重试:打印失败自动重试2-3次,仍失败则标记异常并通知店员
  • 状态同步:定期查询作业状态,更新订单的打印进度(待打印/打印中/已完成/失败)

内容的提问来源于stack exchange,提问作者Patato

火山引擎 最新活动