如何在.NET MAUI中获取Mac设备的已安装打印机列表
问题描述
我正在开发一款仅面向桌面端的.NET MAUI应用,同时支持Mac和Windows系统,需要实现获取设备已安装打印机列表的功能。Windows端通过System.Drawing.Printing.PrinterSettings.InstalledPrinters已经实现,但Mac端遇到了以下问题:
- 无法直接使用AppKit命名空间的
NSPrinter.PrinterNames属性 - 尝试用底层Objective-C消息调用获取打印机列表时,得到空结果;如果先调用
alloc再调用printerNames,会抛出Unrecognized selector printerNames when sent to class异常
我编写的调用代码如下:
[DllImport("/usr/lib/libobjc.dylib", EntryPoint = "objc_msgSend")] public static extern IntPtr IntPtr_objc_msgSend(IntPtr receiver, IntPtr selector); [DllImport("/usr/lib/libobjc.dylib", EntryPoint = "objc_getClass")] public static extern IntPtr objc_getClass(string className); // 获取打印机列表逻辑 IntPtr clsNSPrinter = objc_getClass("NSPrinter"); IntPtr selPrinterNames = ObjCRuntime.Selector.GetHandle("printerNames"); IntPtr printerNamesPtr = IntPtr_objc_msgSend(clsNSPrinter, selPrinterNames); var printersNSArray = Runtime.GetNSObject<NSArray>(printerNamesPtr); var printerNames = NSArray.StringArrayFromHandle(printersNSArray.Handle); return printerNames.ToList();
注:在支持AppKit的Xamarin.Mac应用中,NSPrinter.PrinterNames能正常返回我设备上的4台打印机。
解决方案
1. 确保AppKit框架被正确链接
.NET MAUI Mac项目默认可能未链接AppKit框架,需要手动配置:
- 打开项目的
.csproj文件 - 在
<PropertyGroup>节点下添加配置:
或者添加框架链接参数:<RuntimeIdentifiers>osx-x64;osx-arm64</RuntimeIdentifiers> <UseAppKit>true</UseAppKit><MtouchExtraArgs>-framework AppKit</MtouchExtraArgs>
2. 修复Objective-C方法调用逻辑
printerNames是类方法,无需调用alloc,直接向NSPrinter类发送消息即可。同时要确保框架提前加载,以及正确解析NSArray对象:
using System.Runtime.InteropServices; using ObjCRuntime; public static List<string> GetInstalledPrintersMac() { // 手动加载AppKit框架 Dlfcn.dlopen("/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit", 0); IntPtr clsNSPrinter = objc_getClass("NSPrinter"); if (clsNSPrinter == IntPtr.Zero) return new List<string>(); IntPtr selPrinterNames = Selector.GetHandle("printerNames"); IntPtr printerNamesPtr = objc_msgSend(clsNSPrinter, selPrinterNames); if (printerNamesPtr == IntPtr.Zero) return new List<string>(); // 遍历NSArray转换为字符串列表 var nsArray = Runtime.GetNSObject<NSArray>(printerNamesPtr); var printerNames = new List<string>(); for (nuint i = 0; i < nsArray.Count; i++) { var strPtr = nsArray.ValueAt(i); var printerName = Runtime.GetNSObject<NSString>(strPtr).ToString(); printerNames.Add(printerName); } return printerNames; } // 匹配类方法调用的objc_msgSend签名 [DllImport("/usr/lib/libobjc.dylib", EntryPoint = "objc_msgSend")] private static extern IntPtr objc_msgSend(IntPtr receiver, IntPtr selector); [DllImport("/usr/lib/libobjc.dylib", EntryPoint = "objc_getClass")] private static extern IntPtr objc_getClass(string className);
3. 推荐方案:使用.NET MAUI原生打印API
.NET MAUI 7.0+提供了跨平台打印支持,无需手动调用Objective-C即可获取打印机列表:
using Microsoft.Maui.Graphics.Printing; public async Task<List<string>> GetAvailablePrintersAsync() { var printManager = PrintManager.Default; var printers = await printManager.GetAvailablePrintersAsync(); return printers.Select(p => p.Name).ToList(); }
注:Mac端需要确保应用有打印权限,可在项目的Info.plist中添加打印相关权限声明。
内容的提问来源于stack exchange,提问作者DesmondMilez
相关产品推荐
相关产品推荐

