Reading status from Zebra Printer

11,701

Solution 1

I'm facing the same problem. Did you already manage anything on this subject?

Ax Perez Parra Castro, this is how I did it:

-get the RawPrinterHelper class from here http://support.microsoft.com/kb/322091

-my printer (zebra 2030) doesn't support ZPL, so as far as I know the only way is to send unicode to it

-I made a list of characters I need e.g.

string enq = Convert.ToChar(5).ToString();
string esc = Convert.ToChar(27).ToString();
string nul = Convert.ToChar(0).ToString();
string rs = Convert.ToChar(30).ToString();
string lf = Convert.ToChar(10).ToString();
string cr = Convert.ToChar(13).ToString();

(get those int values from en.wikipedia.org/wiki/ASCII)

-compose the command - e.g. sb.Append(esc + enq + Convert.ToChar(7).ToString()); (from the printer manual, the command < ESC>< ENQ><7> should get the firmware version)

-send the command RawPrinterHelper.SendStringToPrinter(printerName, sb.ToString()); (printerName in my case is "Zebra TTP 2030")

Solution 2

ReadPrinter will not help in this situation. It will read back the print job you have submitted to the printer, not the printer's response. However, for the sake of completeness: In order to use ReadPrinter, you must open the printer again, using the combined "printer name - job id" syntax:

OpenPrinter("Zebra,Job 12345", ...);
ReadPrinter(hPrinter, ...);

This will only work if the job 12345 has not been removed yet.


As for answering the question, you have to use WriteFile to send data and ReadFile to get the response. To use those functions, you need to open the printer with CreateFile. After you've done that, the rest is absolutely trivial.

The problem here is getting the device path that must be passed to CreateFile in order to open the printer. If your printer is an LPT one, that's as simple as "LPT:", but for a USB printer you have to obtain the device path, which looks like this:

\\?\usb#vid_0a5f&pid_0027#46a072900549#{28d78fad-5a12-11d1-ae5b-0000f803a8c2}

I have found a way to obtain this path, but it only works if you have just one printer installed. If you have more, you will need a relation between the device path and the printer name you see in the control panel, and that relation is something I haven't figured yet. I've created a question for that: Figuring which printer name corresponds to which device ID.

Share:
11,701

Related videos on Youtube

pmoreira
Author by

pmoreira

I am an experienced web developer, a former startup CTO and founder, with experience in creating products, building software, designing architecture and planning infrastructure, scaling from zero to post seed-stage. Prior to becoming a freelancer I spent the last 5 years as the CTO of a startup, where I helped them grow from an idea to an MVP, to seed funding and grow into a sustainable business. I can help startups define the MVP, set up software product development and tools, and prepare a cost-effective infrastructure that suits their needs. I can design the right architecture for your current needs, without over-engineering solutions, but leaving room for the architecture to evolve and grow as your needs change. I can work with existing code to optimize performance, refactor it for improved code quality and help you manage and reduce your technical debt.

Updated on January 11, 2020

Comments

  • pmoreira
    pmoreira over 4 years

    I'm working on a project where we need to use a Zebra Printer for barcode labels. We're using C#, and we're doing OK on the printing side of things, sending raw ZPL strings to the printer (using winspool.drv).

    However, we also need to read from the printer, and no luck there.

    We need to get the status from the printer, which is the output to the ZPL command "~HS", so we can tell how many labels are in memory waiting to be printed. The EnumJobs() from winspool.drv only has jobs on the windows spool, and once they're sent to the printer, they're gone from that list. But that doesn't mean the label has been printed, since the printer has a peel sensor and only prints one label at a time, and we're obviously interested in sending batches of labels to the printer.

    I've tried something like (using the winspool.drv calls):

    OpenPrinter(szPrinterName, out hPrinter, IntPtr.Zero);
    WritePrinter(hPrinter, pBytes, dwCount, out dwWritten); // send the string "~HS"
    ReadPrinter(hPrinter, data, buff, out pcRead);
    

    But I get nothing on the ReadPrinter call. I don't even know if this is the right way of going at it.

    Anyone out there tackled this before?

    Thanks.

  • Admin
    Admin over 9 years
    where are the WriteFile and ReadFile located - I couldn't find them in winspool.drv (see msdn.microsoft.com/en-us/library/windows/desktop/…)
  • Admin
    Admin over 9 years
    are you sure that you can't read data with .ReadPrinter?? msdn.microsoft.com/en-us/library/windows/desktop/… says: "The ReadPrinter function retrieves data from the specified printer."
  • aelveborn
    aelveborn over 9 years
    @AndreasNiedermair Yes, it retrieves data from the printer, but it is the data you put in that printer yourself (your printjob), not the data printer may generate in response to the printjob. WriteFile and ReadFile are general purpose Windows functions that work on many different objects including printers, they are in kernel32.dll.
  • Admin
    Admin over 9 years
    thanks for your input. so you are basically saying that with winspool.drv there's no chance to read a response, but one should fall back to the basic kernel32.dll (which is vanilla usb without any driver)?
  • aelveborn
    aelveborn over 9 years
    @AndreasNiedermair It is so as far as I know (you can also check out the linked question of mine). There is a driver involved though, because to use it you need to have the printer installed properly, which requires a driver.
  • bfi
    bfi over 9 years
    @AndreasNiedermair it was a few years ago, so I don't remember the details. Please see if this experimental project helps dropbox.com/s/2h6gj0o08eksbxu/PrintLabel.zip?dl=0