从 Zebra 打印机读取状态
我正在开展一个项目,我们需要使用 Zebra 打印机来打印条形码标签。 我们使用 C#,并且在打印方面做得很好,将原始 ZPL 字符串发送到打印机(使用 Winspool.drv)。
然而,我们还需要从打印机读取数据,但运气不佳。
我们需要从打印机获取状态,这是 ZPL 命令“~HS”的输出,这样我们就可以知道内存中有多少标签等待打印。 winspool.drv 中的 EnumJobs() 仅在 Windows 假脱机上有作业,一旦它们被发送到打印机,它们就会从该列表中消失。但这并不意味着标签已被打印,因为打印机具有剥离传感器并且一次仅打印一张标签,并且我们显然有兴趣将批量标签发送到打印机。
我尝试过类似的方法(使用winspool.drv调用):
OpenPrinter(szPrinterName, out hPrinter, IntPtr.Zero);
WritePrinter(hPrinter, pBytes, dwCount, out dwWritten); // send the string "~HS"
ReadPrinter(hPrinter, data, buff, out pcRead);
但我在ReadPrinter调用中什么也没得到。我什至不知道这是否是正确的做法。
之前有人解决过这个问题吗?
谢谢。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我面临着同样的问题。您已经在这个主题上做过任何事情了吗?
Ax Perez Parra Castro,我就是这样做的:
- 从这里获取 RawPrinterHelper 类 http://support .microsoft.com/kb/322091
-我的打印机(zebra 2030)不支持ZPL,所以据我所知唯一的方法是将unicode发送给它
-我制作了一个我需要的字符列表,例如
(从 en.wikipedia.org/wiki/ASCII 获取这些 int 值)
- 编写命令 - 例如<7> 应该获取固件版本)
sb.Append(esc + enq + Convert.ToChar(7).ToString());
(从打印机手册中,命令- 发送命令
RawPrinterHelper.SendStringToPrinter(printerName, sb.ToString());
(我的打印机名称是“Zebra TTP 2030”)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.
(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")在这种情况下,
ReadPrinter
将无济于事。它将读回您提交给打印机的打印作业,而不是打印机的响应。但是,为了完整起见:为了使用ReadPrinter
,您必须再次打开打印机,使用组合的“打印机名称 - 作业 ID”语法:这只会如果作业 12345 尚未删除,则继续工作。
至于回答问题,您必须使用
WriteFile
发送数据并使用ReadFile
获取响应。要使用这些功能,您需要使用CreateFile
打开打印机。当你完成这些之后,剩下的就完全是微不足道的了。这里的问题是获取必须传递给 CreateFile 才能打开打印机的设备路径。如果您的打印机是 LPT 打印机,则就像
"LPT:"
一样简单,但对于 USB 打印机,您必须获取设备路径,如下所示:我找到了一个 获取此路径的方法,但仅当您只安装一台打印机时才有效。如果您有更多,您将需要在控制面板中看到的设备路径和打印机名称之间的关系,而这种关系我还没有弄清楚。我为此创建了一个问题:计算对应的打印机名称到哪个设备ID。
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 useReadPrinter
, you must open the printer again, using the combined "printer name - job id" syntax: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 andReadFile
to get the response. To use those functions, you need to open the printer withCreateFile
. 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: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.
大约 15 年前,我编写了通过 Zebra 打印机进行打印的软件。
当时我们通过 RS-232(?标准串行通信)与打印机进行通信,效果很好,所有信息都从打印机及时准确地返回。
最近我使用 Epson 理货打印机,发现 Windows 打印机驱动程序笨拙且低效。我降低了一个级别并通过 GDI 直接与打印机通信,一切都令我满意。
我说去掉中间人,如果你降低一个级别并直接与打印机通信,而不是通过Windows打印机驱动程序通信,你会取得更大的成功。
希望这有帮助,
About 15 years ago I wrote software to print throught Zebra printers.
At the time we communicated with the printer over RS-232 (? standard serial comms), which worked well, all information came back from the printer in a timely and accurate fashion.
Recently I'd to work with Epson tally printers, and found the windows printer drivers clumsy and inefficient. I dropped down a level and communicated directly with the printer through GDI, and everything worked to my satisification.
I say take out the middle man, if you drop down a level and communicate with the printer directly, rather than communicating through windows printer drivers, you'll have more success.
Hope this helps,
如果您有机会使用
kernel32.dll
并省略 USB 驱动程序绑定的winspool.srv
,您可以使用这种普通方法:否则有一个可用的解决方案(虽然是 VB.NET) (但我不知道这是否适用于 ZPL /EPL/fingerprint/...-printers)使用
GetPrinter
与PRINTER_INFO_2
。pinvoke.net 上还提供了翻译。
If you have the chance to use
kernel32.dll
and leaving out the usb-driver-boundwinspool.srv
you could use this vanilla approach:Otherwise there's a solution available (it's VB.NET though) (but I can't tell if this works with ZPL/EPL/fingerprint/...-printers) which uses
GetPrinter
withPRINTER_INFO_2
.There's also a translation at pinvoke.net available.
我使用了 C++ 的 TCP/IP 通信,并且能够从打印引擎做出响应。
I have used TCP/IP communication with C++, and I was able to response from the print engine.