.NET中使用WMI获取打印机状态时遭遇NotFound错误问题
你的.NET Core项目中使用WMI查询Win32_Printer时,即便传入正确的打印机名称仍报“Not Found”错误,可从以下几个方向排查解决:
1. 查询语句的转义与语法问题
直接用字符串拼接生成WMI查询时,若打印机名称包含单引号、空格或特殊字符,会导致语法错误,直接查不到结果。比如名称为Mike's Printer时,拼接后的语句会出现单引号冲突,触发查询失败。
解决方式:使用参数化查询或手动转义特殊字符:
// 方法1:手动转义单引号 string escapedPrinterName = printerName.Replace("'", "''"); string query = $"SELECT * from Win32_Printer WHERE NAME = '{escapedPrinterName}'"; // 方法2:参数化查询(更安全) string query = "SELECT * from Win32_Printer WHERE NAME = @printerName"; var searcher = new ManagementObjectSearcher(); searcher.Query = new ObjectQuery(query); var parameters = new ManagementBaseObject(); parameters["printerName"] = printerName; searcher.Query.Parameters.Add(parameters);
2. WMI访问权限限制
.NET Core默认运行权限可能不足以读取WMI打印机信息,尤其是非管理员身份运行时;若查询远程打印机,还需目标机器开启WMI服务并配置对应权限。
解决方式:
- 尝试以管理员身份启动程序,验证是否能正常查询。
- 远程查询场景:在目标机器的「计算机管理」→「服务和应用程序」→「WMI控制」中,给当前用户分配WMI远程访问权限,同时确保目标机器的WMI服务(Winmgmt)处于运行状态。
3. 打印机名称匹配偏差
Win32_Printer的Name字段可能和系统显示的打印机名称不一致,比如网络打印机的Name会包含完整路径(如\\print-server\HP-LaserJet),而你传入的是本地简化名称。
解决方式:先枚举所有打印机,确认目标打印机的真实Name值:
var searcher = new ManagementObjectSearcher("SELECT Name, DeviceID FROM Win32_Printer"); foreach (var printer in searcher.Get()) { _logger.LogInformation($"真实Name: {printer["Name"]}, DeviceID: {printer["DeviceID"]}"); }
用查询到的真实Name作为参数传入方法,再测试查询效果。
4. .NET Core的WMI兼容性问题
.NET Core对传统WMI的支持不如.NET Framework完善,部分场景下会出现查询异常。可改用微软推荐的Microsoft.Management.Infrastructure(MMI)库替代System.Management。
示例代码(MMI实现):
using Microsoft.Management.Infrastructure; public async Task<Response> PrinterStateByName(string sessionId, string printerName) { try { var cimSession = CimSession.Create(null); // 本地会话 var escapedName = printerName.Replace("'", "''"); var query = $"SELECT * FROM Win32_Printer WHERE Name = '{escapedName}'"; var printers = cimSession.QueryInstances(@"root\cimv2", "WQL", query); foreach (var printer in printers) { string name = printer.CimInstanceProperties["Name"].Value.ToString(); string status = printer.CimInstanceProperties["Status"].Value?.ToString(); bool isDefault = (bool)printer.CimInstanceProperties["Default"].Value; bool isOnline = !(bool)printer.CimInstanceProperties["WorkOffline"].Value; bool isOutOfPaper = (bool)printer.CimInstanceProperties["OutOfPaper"].Value; _logger.LogInformation($"Printer Name: {name}"); _logger.LogInformation($"Printer State: {status}"); _logger.LogInformation($"Is Printer Default: {isDefault}"); _logger.LogInformation($"Online state: {isOnline}"); _logger.LogInformation($"Out of the Paper: {isOutOfPaper}"); } } catch (CimException e) { _logger.LogError($"Error during getting informations about: {e.Message}"); } var result = await _mediator.Send(new SendPrinterStateByName_Command(printerName)); return new Response(false, result, null, sessionId); }
注:需先安装NuGet包Microsoft.Management.Infrastructure。
5. 异步代码的小问题
你的方法标记为async Task<Response>,但调用_mediator.Send时未加await,会导致返回结果时任务未完成,可能引发逻辑异常,建议修正为:
var result = await _mediator.Send(new SendPrinterStateByName_Command(printerName));
内容的提问来源于stack exchange,提问作者Petr Barabáš

