如何在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
相关产品推荐
相关产品推荐

