问题 c#检查打印机状态


在我的应用程序(Windows 7,VS2010)中,我必须在成功打印图像后减少信用计数器。 无论如何,在开始整个过程​​之前,我想了解打印机状态,以便在纸张,卡纸等方面提醒用户。 现在,环顾四周我发现了几个使用Windows WMI的例子,但是......从来没有用过。运用 这个 例如,如果我取出纸张,打开盖子,打印机状态也始终准备就绪...关闭打印机。

现在打印机状态总是很好,我正在办公室测试打印机在家里舒适地关闭。 让我用炸药引爆设备以获得打印机错误状态?

这是我用过的代码

ManagementObjectCollection MgmtCollection;
ManagementObjectSearcher MgmtSearcher;

//Perform the search for printers and return the listing as a collection
MgmtSearcher = new ManagementObjectSearcher("Select * from Win32_Printer");
MgmtCollection = MgmtSearcher.Get();

foreach (ManagementObject objWMI in MgmtCollection)
{

    string name = objWMI["Name"].ToString().ToLower();

    if (name.Equals(printerName.ToLower()))
    {

        int state = Int32.Parse(objWMI["ExtendedPrinterStatus"].ToString());
        if ((state == 1) || //Other
        (state == 2) || //Unknown
        (state == 7) || //Offline
        (state == 9) || //error
        (state == 11) //Not Available
        )
        {
        throw new ApplicationException("hope you are finally offline");
        }

        state = Int32.Parse(objWMI["DetectedErrorState"].ToString());
        if (state != 2) //No error
        {
        throw new ApplicationException("hope you are finally offline");
        }

    }

}

其中'printerName'作为参数被接收。

谢谢你的建议。


1618
2018-02-15 09:37


起源

当你找到有效的东西时,请记住你必须应对出现的任何或所有这些情况 如 你也打印 - 炸药可能会在检查状态和实际开始打印作业之间消失。 - Damien_The_Unbeliever
可以归咎于WMI。大多数打印机驱动程序都没有正确更新打印机状态以供WMI选择。我们曾多次面对它 - Mubashir Khan
你在看什么打印机? - Nitin Unni
@Mubashir Khan:你说得对。如果打印机驱动程序绕过假脱机程序进程以获取状态,或者它根本没有向假脱机程序报告状态,则WMI无法告知打印机从假脱机程序进程检索它时的实际状态。更多细节: stackoverflow.com/questions/14455964/... - Derek W


答案:


你没有说你正在使用什么版本的.Net,但是从.Net 3.0开始就有了一些很好的打印功能。我已经使用了这个,虽然我不能确定它报告各种状态级别,但我确实看到过各种打印机等“Toner Low”等消息。

PrinterDescription是一个自定义类,但您可以看到它使用的属性。

http://msdn.microsoft.com/en-us/library/system.printing.aspx

        PrintQueueCollection printQueues = null;
        List<PrinterDescription> printerDescriptions = null;

        // Get a list of available printers.
        this.printServer = new PrintServer();
        printQueues = this.printServer.GetPrintQueues(new[] { EnumeratedPrintQueueTypes.Local, EnumeratedPrintQueueTypes.Connections });
        printerDescriptions = new List<PrinterDescription>();

        foreach (PrintQueue printQueue in printQueues)
        {
            // The OneNote printer driver causes crashes in 64bit OSes so for now just don't include it.
            // Also redirected printer drivers cause crashes for some printers. Another WPF issue that cannot be worked around.
            if (printQueue.Name.ToUpperInvariant().Contains("ONENOTE") || printQueue.Name.ToUpperInvariant().Contains("REDIRECTED"))
            {
                continue;
            }

            string status = printQueue.QueueStatus.ToString();

            try
            {
                PrinterDescription printerDescription = new PrinterDescription()
                {
                    Name = printQueue.Name,
                    FullName = printQueue.FullName,
                    Status = status == Strings.Printing_PrinterStatus_NoneTxt ? Strings.Printing_PrinterStatus_ReadyTxt : status,
                    ClientPrintSchemaVersion = printQueue.ClientPrintSchemaVersion,
                    DefaultPrintTicket = printQueue.DefaultPrintTicket,
                    PrintCapabilities = printQueue.GetPrintCapabilities(),
                    PrintQueue = printQueue
                };

                printerDescriptions.Add(printerDescription);
            }
            catch (PrintQueueException ex)
            {
                // ... Logging removed
            }
        }

9
2018-02-03 14:37



如果我将一个页面从控制台应用程序直接打印到打印机(使用verb =“print”进程并将.pdf提供给它);是否可以跟踪打印队列是否成功打印文档?(对于特定文档?) - flute
我使用.Net 4.5,在.Net 4.5中不可用 - Amirhossein Yari


打印队列 在课堂上 System.Printing 命名空间就是你所追求的。它具有许多属性,可提供有关其所代表的打印机状态的有用信息。这里有些例子;

        var server = new LocalPrintServer();

        PrintQueue queue = server.DefaultPrintQueue;

        //various properties of printQueue
        var isOffLine = queue.IsOffline;
        var isPaperJam = queue.IsPaperJammed;
        var requiresUser = queue.NeedUserIntervention;
        var hasPaperProblem = queue.HasPaperProblem;
        var isBusy = queue.IsBusy;

这绝不是一个全面的列表,并且记住队列可能具有一个或多个这些状态,因此您必须考虑处理它们的顺序。


7
2018-04-30 13:39



实际上,我撤回我的评论,这不起作用。 - Yusha
您只是在阅读默认打印机。系统可以在其上安装多个打印机,每个打印机都有自己的队列和自身状态 - AaA


所有品牌的打印机唯一可靠的解决方案是使用SNMP查询打印的页数,并确保它与发送的文档中的页数相匹配。

页面计数的SNMP OID是1.3.6.1.2.1.43.10.2.1.4

从我的测试来看,每个其他策略都有不可靠的行为(重复获取打印队列时出现奇数空引用异常)或提供了不准确的状态代码或页数。


0
2018-01-21 17:05