119 lines
3.7 KiB
C#
119 lines
3.7 KiB
C#
|
|
using CloudPrint.Client.Models;
|
||
|
|
using System.Management;
|
||
|
|
|
||
|
|
namespace CloudPrint.Client.Services.Printing;
|
||
|
|
|
||
|
|
public sealed class WindowsPrinterStatusReader : IPrinterStatusReader
|
||
|
|
{
|
||
|
|
public PrinterStatusSnapshot Read(string printerName)
|
||
|
|
{
|
||
|
|
if (string.IsNullOrWhiteSpace(printerName))
|
||
|
|
{
|
||
|
|
return new PrinterStatusSnapshot { Status = PrinterStatus.Unknown, Message = "打印机名称为空" };
|
||
|
|
}
|
||
|
|
|
||
|
|
try
|
||
|
|
{
|
||
|
|
return ReadCore(printerName);
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
return new PrinterStatusSnapshot
|
||
|
|
{
|
||
|
|
Status = PrinterStatus.Unknown,
|
||
|
|
Message = $"状态读取失败:{ex.Message}"
|
||
|
|
};
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static PrinterStatusSnapshot ReadCore(string printerName)
|
||
|
|
{
|
||
|
|
using var searcher = new ManagementObjectSearcher(
|
||
|
|
"SELECT Name, WorkOffline, PrinterStatus, DetectedErrorState FROM Win32_Printer");
|
||
|
|
|
||
|
|
foreach (ManagementObject printer in searcher.Get())
|
||
|
|
{
|
||
|
|
var name = Convert.ToString(printer["Name"]);
|
||
|
|
if (!string.Equals(name, printerName, StringComparison.OrdinalIgnoreCase))
|
||
|
|
{
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
var workOffline = Convert.ToBoolean(printer["WorkOffline"] ?? false);
|
||
|
|
var printerStatus = Convert.ToUInt32(printer["PrinterStatus"] ?? 2u);
|
||
|
|
var errorState = Convert.ToUInt32(printer["DetectedErrorState"] ?? 0u);
|
||
|
|
var queueCount = CountQueueJobs(printerName);
|
||
|
|
|
||
|
|
var status = MapStatus(workOffline, printerStatus, errorState, queueCount);
|
||
|
|
return new PrinterStatusSnapshot
|
||
|
|
{
|
||
|
|
Status = status,
|
||
|
|
QueueCount = queueCount,
|
||
|
|
Message = BuildMessage(workOffline, printerStatus, errorState)
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
return new PrinterStatusSnapshot
|
||
|
|
{
|
||
|
|
Status = PrinterStatus.Offline,
|
||
|
|
Message = "未找到打印机"
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
private static int CountQueueJobs(string printerName)
|
||
|
|
{
|
||
|
|
var escapedName = printerName.Replace("\\", "\\\\", StringComparison.Ordinal).Replace("'", "''", StringComparison.Ordinal);
|
||
|
|
using var searcher = new ManagementObjectSearcher($"SELECT Name FROM Win32_PrintJob WHERE Name LIKE '{escapedName},%'");
|
||
|
|
return searcher.Get().Count;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static PrinterStatus MapStatus(bool workOffline, uint printerStatus, uint errorState, int queueCount)
|
||
|
|
{
|
||
|
|
if (workOffline || printerStatus == 7)
|
||
|
|
{
|
||
|
|
return PrinterStatus.Offline;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (errorState is >= 3 and <= 11 || printerStatus == 6)
|
||
|
|
{
|
||
|
|
return PrinterStatus.Error;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (printerStatus == 4 || queueCount > 0)
|
||
|
|
{
|
||
|
|
return PrinterStatus.Printing;
|
||
|
|
}
|
||
|
|
|
||
|
|
return printerStatus == 3 ? PrinterStatus.Idle : PrinterStatus.Unknown;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static string BuildMessage(bool workOffline, uint printerStatus, uint errorState)
|
||
|
|
{
|
||
|
|
if (workOffline)
|
||
|
|
{
|
||
|
|
return "脱机";
|
||
|
|
}
|
||
|
|
|
||
|
|
return errorState switch
|
||
|
|
{
|
||
|
|
3 => "缺纸",
|
||
|
|
4 => "卡纸",
|
||
|
|
5 => "碳粉不足",
|
||
|
|
6 => "门打开",
|
||
|
|
7 => "需要人工干预",
|
||
|
|
8 => "离线",
|
||
|
|
9 => "维修中",
|
||
|
|
10 => "输出纸盘已满",
|
||
|
|
11 => "缺纸",
|
||
|
|
_ => printerStatus switch
|
||
|
|
{
|
||
|
|
3 => "就绪",
|
||
|
|
4 => "打印中",
|
||
|
|
5 => "预热中",
|
||
|
|
6 => "已停止",
|
||
|
|
7 => "离线",
|
||
|
|
_ => string.Empty
|
||
|
|
}
|
||
|
|
};
|
||
|
|
}
|
||
|
|
}
|