Question

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

Was it helpful?

Solution 2

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.

OTHER TIPS

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");
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top