使用RawPrinterHelper类查询Zebra打印机状态

时间:2011-11-22 20:26:13

标签: printing status zebra-printers thermal-printer zpl

我正在使用Microsoft的RawPrinterHelperhttp://support.microsoft.com/kb/322091从C#代码打印到Zebra KR403打印机,一切正常。

我希望监控打印机的卡纸和纸张停机状态。我找到了一个可以发送到打印机的查询,“~HQES”或“esc eng 6”,它将返回我需要的所有内容。问题是我无法弄清楚如何将此查询发送到允许打印机响应的打印机。 WritePrinter类中的RawPrinterHelper似乎只返回bool或long类型。

我还尝试使用Win32_printer对象来查找打印机的PrinterStatus/PrinterState/Errors。使用以下方法:

public static string PrinterStateCheck(string szPrinterName)
    {
        string query = string.Format("SELECT * from Win32_Printer WHERE Name LIKE '%{0}%'", szPrinterName);
        ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
        ManagementObjectCollection collection = searcher.Get();
        string errorName = "";
        foreach (ManagementObject printer in collection)
        {
            int state = Convert.ToInt32(printer["PrinterState"]);
            errorName = state.ToString();
        }
        return errorName;

利用这种方法,我尝试了PrinterStatePrinterStatusDetectedErrorState,但这些都没有响应我需要的信息。 PrinterState始终返回1024PrinterStatus始终返回4DetectedErrorState始终返回2。虽然PrinterState确实在正确的打印上返回了0而在paperjam或媒体输出事件上返回1024以进行一些打印,但现在它只会在每次调用时返回1024。 / p>

我还发现Zebra创建了自己的软件来监控网络上的打印机。问题是我们的打印机不在网络上,只通过USB连接到客户端计算机。此外,我们希望在每张收据打印之前或之后检查打印机的状态。

我希望winspool.Drv可以使用一些内容将原始数据发送到打印机并从打印机接收数据。

现在我正在使用ReadPrinter的{​​{1}}函数,但函数返回winspool.Drv,这意味着无法访问打印机的响应。这通常意味着打印机没有设置为双向通信,但我确信它是。在“打印机属性”的“端口”选项卡中选中“启用双向支持”复选框。此外,Zebra设置实用程序可以正确查询打印机并在其直接通信窗口中接收响应。

感谢您的任何建议,

杰里米

2 个答案:

答案 0 :(得分:1)

我做了一些非常相似的事情,我可以告诉你,几乎没有办法监控.NET中的打印作业。

我已经接近了,做了以下事情:

  1. 创建一个“PrinterDiagnosticsFacade”,用于查询.NET PrintQueue对象的状态和WMI。两者都不准确。合并两者的数据以确定打印机的真实状态。

  2. 调整打印机的设置,以便打印作业保留在队列中。这样,您可以通过对打印假脱机作业执行WMI查询来准确读取打印作业的状态。 (您可以匹配打印文件名)

  3. 这就是我如何接近获得打印机状态。

    添加代码以显示如何使用.NET打印队列对象完成:

    有关启动代码的printqueue对象,请参阅http://msdn.microsoft.com/en-us/library/system.printing.printqueue.aspx

    PrintQueue me = Queue; 
    if (me != null)
    {
        me.Refresh();
        //in this if else,
        //i purposefully put the ones that error out first
        //so that if multiple can be true at the same time
        //the errors will definitely take precedence
        if (me.HasPaperProblem)
        {
            _SystemDotPrintingStatus = new PrinterStatus(PrinterStatusType.Error, "Error: Has paper problem");
        }
        else if (me.IsDoorOpened)
        {
            _SystemDotPrintingStatus = new PrinterStatus(PrinterStatusType.Error, "Error: Door is open");
        }
        else if (me.IsManualFeedRequired)
        {
            _SystemDotPrintingStatus = new PrinterStatus(PrinterStatusType.Error, "Error: Printer needs manually fed");
        }
        else if (me.IsNotAvailable)
        {
            _SystemDotPrintingStatus = new PrinterStatus(PrinterStatusType.Error, "Error: Printer not available");
        }
    
        else if (me.IsOutOfMemory)
        {
            _SystemDotPrintingStatus = new PrinterStatus(PrinterStatusType.Error, "Error: Printer is out of memory");
        }
        else if (me.IsOutOfPaper)
        {
            _SystemDotPrintingStatus = new PrinterStatus(PrinterStatusType.Error, "Error: Printer is out of paper");
        }
        else if (me.IsOutputBinFull)
        {
            _SystemDotPrintingStatus = new PrinterStatus(PrinterStatusType.Error, "Error: Printer output bin is full");
        }
        else if (me.IsPaperJammed)
        {
            _SystemDotPrintingStatus = new PrinterStatus(PrinterStatusType.Error, "Error: Paper jam");
        }
        else if (me.IsOffline)
        {
            _SystemDotPrintingStatus = new PrinterStatus(PrinterStatusType.Offline, "Offline");
        }
        else if (me.IsBusy)
        {
            _SystemDotPrintingStatus = new PrinterStatus(PrinterStatusType.Busy, "Busy");
        }
        else if (me.IsInitializing)
        {
            _SystemDotPrintingStatus = new PrinterStatus(PrinterStatusType.Busy, "Initializing");
        }
        else if (me.IsIOActive)
        {
            _SystemDotPrintingStatus = new PrinterStatus(PrinterStatusType.Busy, "Sending and recieving data");
        }
        else if (me.IsProcessing)
        {
            _SystemDotPrintingStatus = new PrinterStatus(PrinterStatusType.Busy, "Processing");
        }
        else if (me.IsWarmingUp)
        {
            _SystemDotPrintingStatus = new PrinterStatus(PrinterStatusType.Busy, "Warming up");
        }
        else if (me.IsPendingDeletion)
        {
            _SystemDotPrintingStatus = new PrinterStatus(PrinterStatusType.Busy, "Deleting a job");
        }
        else if (me.IsPaused)
        {
            _SystemDotPrintingStatus = new PrinterStatus(PrinterStatusType.Paused, "Paused");
        }
        else if (me.IsPrinting)
        {
            _SystemDotPrintingStatus = new PrinterStatus(PrinterStatusType.Printing, "Printing");
        }
        else if (me.IsPowerSaveOn)
        {
            _SystemDotPrintingStatus = new PrinterStatus(PrinterStatusType.Ready, "In power save mode");
        }
        else
            _SystemDotPrintingStatus = new PrinterStatus(PrinterStatusType.Ready, "Ready");
    }
    

答案 1 :(得分:1)

我们最终使用的问题的解决方案是为打印机创建WinUSB驱动程序。这样,设备被视为USB设备。使用驱动程序创建了ZebraUSB对象,并创建了一个名为WriteRead的方法。我们使用WriteRead方法将~HQES查询发送到打印机并收到回复。有时在查询和响应之间存在一些延迟时间。为了解决这个问题,我们将响应设置为变量并使用不同的方法检索它。

我不确定代码的细节,因为我没有对WinUSB驱动程序进行编码,而且我无法访问其代码。

这个答案的要点是我们必须在任何状态查询工作之前为打印机创建一个WinUSB驱动程序。