You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在MacOS上通过Swift结合CUPS库彻底移除已连接打印机?

在macOS上通过Swift调用CUPS彻底移除打印机

要解决系统设置中仍可见已移除打印机的问题,核心是确保拥有管理员权限并正确使用CUPS API的参数,以下是具体实现步骤:

1. 配置CUPS桥接

首先需要在Swift项目中引入CUPS的C头文件:

  • 创建桥接文件(例如CUPSSwift-Bridging-Header.h),添加:
    #include <cups/cups.h>
    
  • 在Xcode项目设置的「Build Settings」中,将「Objective-C Bridging Header」指向该文件。

2. 带权限移除打印机的Swift实现

移除打印机需要管理员权限,以下代码结合Security框架请求授权,并调用CUPS API彻底删除所有打印机:

import Foundation
import Security

func removeAllPrinters() {
    // 请求管理员授权
    var authRef: AuthorizationRef?
    let authStatus = AuthorizationCreate(nil, nil, [.interactionAllowed, .preAuthorize, .extendRights], &authRef)
    
    guard authStatus == errAuthorizationSuccess, let auth = authRef else {
        print("授权失败,无法修改打印机设置")
        return
    }
    defer { AuthorizationFree(auth, .destroyRights) }
    
    // 获取所有已安装的打印机
    var dests: UnsafeMutablePointer<cups_dest_t>?
    let destCount = cupsGetDests(&dests)
    
    guard destCount > 0, let printers = dests else {
        print("未检测到已安装的打印机")
        return
    }
    defer { cupsFreeDests(destCount, printers) }
    
    // 逐个移除打印机,使用CUPS_REMOVE_ALL确保删除所有实例
    for index in 0..<destCount {
        let printer = printers[Int(index)]
        let printerName = String(cString: printer.name)
        
        let removeStatus = cupsRemoveDest(printer.name, printer.instance, nil, CUPS_REMOVE_ALL)
        if removeStatus == 0 {
            print("已彻底移除打印机:\(printerName)")
        } else {
            print("移除打印机\(printerName)失败:\(cupsLastErrorString())")
        }
    }
    
    // 刷新系统设置显示(可选)
    try? Process.run(URL(fileURLWithPath: "/usr/bin/killall"), arguments: ["System Settings"])
}

// 执行移除操作
removeAllPrinters()

3. 关键注意事项

  • 权限问题:修改打印机配置必须拥有管理员权限,上述代码通过Security框架请求用户授权,GUI程序也可通过SMJobBless实现后台权限提升。
  • CUPS_REMOVE_ALL标志:该参数会删除打印机的所有实例(包括网络打印机的多个连接),如果仅使用默认参数,可能只移除临时连接而非彻底删除系统中的打印机条目。
  • 系统设置刷新:移除后若系统设置仍显示打印机,可通过killall System Settings重启设置进程,或等待系统自动刷新缓存。

替代方案:调用lpadmin命令

也可通过执行CUPS的命令行工具lpadmin实现移除,本质与API调用一致:

func executePrivilegedCommand(_ command: String) {
    var authRef: AuthorizationRef?
    let status = AuthorizationCreate(nil, nil, [.interactionAllowed], &authRef)
    guard status == errAuthorizationSuccess, let auth = authRef else { return }
    
    let task = Process()
    task.executableURL = URL(fileURLWithPath: "/bin/zsh")
    task.arguments = ["-c", command]
    
    var authItem = AuthorizationItem(name: kAuthorizationRightExecute, valueLength: 0, value: nil, flags: 0)
    var authRights = AuthorizationRights(count: 1, items: &authItem)
    let flags = AuthorizationFlags()
    
    AuthorizationExecuteWithPrivileges(auth, task.executableURL?.path, flags, task.arguments, nil)
}

// 移除所有打印机
executePrivilegedCommand("lpstat -p | awk '{print $2}' | xargs -I {} lpadmin -x {}")

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 03:11:13