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

发布于 2024-12-17 09:56:58 字数 1881 浏览 3 评论 0原文

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

我希望监控打印机的卡纸和缺纸状态。我找到了一个可以发送到打印机的查询“~HQES”或“esc eng 6”,它将返回我需要的一切。问题是我不知道如何将此查询发送到打印机以允许打印机响应。 RawPrinterHelper 类中的 WritePrinter 似乎仅返回 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,在卡纸或介质耗尽事件时返回 1024 进行几次打印,但现在它只返回 <每次调用时代码>1024。

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

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

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

感谢您的任何建议,

杰里米

I'm using the RawPrinterHelper class from Microsoft, http://support.microsoft.com/kb/322091, to print to a Zebra KR403 printer from C# code, and everything is working fine.

I wish to monitor the status of the printer for paper jams and paper outages. I've found a query that I can send to the printer, "~HQES" or "esc eng 6", that will return everything I need. The problem is that I can not figure out how to send this query to the printer that will allow the printer to respond. The WritePrinter in the RawPrinterHelper class only seems to return a bool or long type.

I also tried using a Win32_printer object to find the PrinterStatus/PrinterState/Errors of the printer. using the following method:

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;

Utilizing this method, I tried getting the PrinterState, PrinterStatus, and DetectedErrorState, but none of these respond with the information I need. PrinterState always returns a 1024, PrinterStatus always returns a 4, and DetectedErrorState always returns a 2. Though PrinterState did return a 0 on a proper printing and 1024 on a paperjam or media out event for a few prints, now it just returns 1024 on every call.

I have also found that Zebra created their own software for monitoring printers on a network. The problem is our printers are not on a network and are only connected to the client computer via USB. Also, we are hoping to check the status of the printer prior to or after each receipt is printed.

I am hoping there is something from the winspool.Drv that I can use to send raw data to the printer and receive data back from the printer.

Now I'm using the ReadPrinter function of the winspool.Drv, but the function is returning 0 which means that a response from the printer cannot be accessed. This usually means that the printer is not setup for bidirectional communication, but I'm sure that it is. The "Enable bidirectional support" check box is checked in the "Ports" tab of the Printer Properties. Also, the Zebra Setup Utilities can correctly query the printer and receive a response in its Direct Communication window.

Thanks for any advice,

Jeremy

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

你曾走过我的故事 2024-12-24 09:56:58

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

不过,我已经很接近了,执行以下操作:

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

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

这就是我接近获取打印机状态的方式。

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

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

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");
}

I've done something very similar and i can tell you that there is almost no way at all to monitor print jobs in .NET.

I've gotten close though, doing the following:

  1. Create a "PrinterDiagnosticsFacade" that queries both the .NET PrintQueue object's status and WMI. Neither are always accurate. Merge the data from both to decide the printer's true status.

  2. Adjust the printer's settings so that print jobs stay in the queue. That way you can accurately read the print job's status by doing a WMI query for the print spool jobs. (You can match against the print filename)

Thats how i got close to getting at printer status.

Adding in code to show how its done using the .NET print queue object:

See http://msdn.microsoft.com/en-us/library/system.printing.printqueue.aspx for the printqueue object that starts the code off

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");
}
活雷疯 2024-12-24 09:56:58

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

我不确定代码的具体情况,因为我没有编写 WinUSB 驱动程序,并且我无权访问其代码。

这个答案的要点是,我们必须先为打印机创建一个 WinUSB 驱动程序,然后才能进行任何状态查询。

The solution to the problem that we ended up utilizing was to create a WinUSB driver for the printer. This way the device is treated as a USB device. A ZebraUSB object was created using the driver and a method called WriteRead was created. Using the WriteRead method we sent the ~HQES query to the printer and received a response. Sometimes there is some lag time between the query and the response. To combat this, we set the response to a variable and retrieve it using a different method.

I'm not sure of the specifics of the code because I did not code the WinUSB driver, and I do not have access to its code.

The main point of this answer is that we had to create a WinUSB driver for the printer before any of the status queries could work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文