从Zebra打印机读取状态

时间:2009-12-04 11:18:11

标签: printing label barcode zebra-printers zpl-ii

我正在开发一个项目,我们需要使用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调用中什么也得不到。我甚至不知道这是否是正确的方法。

之前有人解决了这个问题吗?

感谢。

5 个答案:

答案 0 :(得分:3)

我面临同样的问题。你有没有关于这个问题的任何事情?

Axe Perez Parra Castro,我就这样做了:

- 从这里http://support.microsoft.com/kb/322091

获取RawPrinterHelper类

-my printer(zebra 2030)不支持ZPL,所以据我所知,唯一的方法就是向它发送unicode

- 我列出了我需要的字符。

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();

(从en.wikipedia.org/wiki/ASCII获取那些int值)

- 组成命令 - 例如sb.Append(esc + enq + Convert.ToChar(7).ToString());(来自打印机手册,命令< ESC>< ENQ>< 7>应该获得固件版本)

- 发送命令RawPrinterHelper.SendStringToPrinter(printerName, sb.ToString());(在我的情况下,printerName是“Zebra TTP 2030”)

答案 1 :(得分:1)

在这种情况下,

ReadPrinter无济于事。它将回读您提交给打印机的打印作业,而不是打印机的响应。但是,为了完整起见:要使用ReadPrinter,您必须使用组合的“打印机名称 - 作业ID”语法打开打印机

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

只有在尚未删除作业12345时才能使用此功能。


至于回答问题,您必须使用WriteFile发送数据,并使用ReadFile来获取回复。要使用这些功能,您需要使用CreateFile打开打印机。在你完成之后,其余部分绝对是微不足道的。

此处的问题是获取必须传递给CreateFile的设备路径才能打开打印机。如果您的打印机是LPT打印机,那就像"LPT:"一样简单,但对于USB打印机,您必须获得设备路径,如下所示:

  

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

我找到了way to obtain this path,但只有在安装了一台打印机的情况下才有效。如果你有更多,你需要设备路径和你在控制面板中看到的打印机名称之间的关系,这种关系是我还没有想到的。我已经为此创建了一个问题:Figuring which printer name corresponds to which device ID

答案 2 :(得分:0)

大约15年前,我编写了通过Zebra打印机打印的软件。

当我们通过RS-232(?标准串行通讯)与打印机通信时,该打印机运行良好,所有信息都以及时准确的方式从打印机返回。

最近我会使用Epson理货打印机,发现Windows打印机驱动程序笨拙且效率低下。我放下了一个级别并通过GDI直接与打印机通信,一切都令我满意。

我说取出中间人,如果你下降一个级别并直接与打印机通信,而不是通过Windows打印机驱动程序进行通信,你将获得更多的成功。

希望这有帮助,

答案 3 :(得分:0)

如果你有机会使用kernel32.dll而忽略了usb-driver-bound winspool.srv,你可以使用这种香草方法:

using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using Microsoft.Win32.SafeHandles;

{
    public class USB
    {
        [DllImport("kernel32.dll", SetLastError = true)]
        internal static extern Int32 CancelIo(SafeFileHandle hFile);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern IntPtr CreateEvent(IntPtr SecurityAttributes,
                                                  Boolean bManualReset,
                                                  Boolean bInitialState,
                                                  String lpName);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern Boolean GetOverlappedResult(SafeFileHandle hFile,
                                                           IntPtr lpOverlapped,
                                                           ref Int32 lpNumberOfBytesTransferred,
                                                           Boolean bWait);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern Boolean ReadFile(SafeFileHandle hFile,
                                                IntPtr lpBuffer,
                                                Int32 nNumberOfBytesToRead,
                                                ref Int32 lpNumberOfBytesRead,
                                                IntPtr lpOverlapped);

        [DllImport("kernel32.dll", SetLastError = true)]
        internal static extern Int32 WaitForSingleObject(IntPtr hHandle,
                                                         Int32 dwMilliseconds);

        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        internal static extern SafeFileHandle CreateFile(String lpFileName,
                                                         UInt32 dwDesiredAccess,
                                                         Int32 dwShareMode,
                                                         IntPtr lpSecurityAttributes,
                                                         Int32 dwCreationDisposition,
                                                         Int32 dwFlagsAndAttributes,
                                                         Int32 hTemplateFile);

        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        internal static extern Boolean WriteFile(SafeFileHandle hFile,
                                                 ref byte lpBuffer,
                                                 Int32 nNumberOfBytesToWrite,
                                                 ref Int32 lpNumberOfBytesWritten,
                                                 IntPtr lpOverlapped);

        [DllImport("kernel32.dll", SetLastError = true)]
        internal static extern int GetLastError();

        private const Int32 FILE_FLAG_OVERLAPPED = 0X40000000;
        private const Int32 FILE_SHARE_READ = 1;
        private const Int32 FILE_SHARE_WRITE = 2;
        private const UInt32 GENERIC_READ = 0X80000000;
        private const UInt32 GENERIC_WRITE = 0X40000000;
        private const Int32 OPEN_EXISTING = 3;
        private const Int32 WAIT_OBJECT_0 = 0;
        private const Int32 WAIT_TIMEOUT = 0x102;
        private const Int32 ReadBufferSize = 200;

        private readonly string _devicePathName;

        public USB(string devicePathName)
        {
            this._devicePathName = devicePathName;
        }

        public void Send(string data)
        {
            var bData = this.Encoding.GetBytes(data);
            this.Send(bData);
        }

        public void Send(byte[] data)
        {
            try
            {
                var eventObject = CreateEvent(IntPtr.Zero,
                                              false,
                                              false,
                                              String.Empty);
                var hidOverlapped = GetHidOverlapped(eventObject);

                var unManagedBuffer = Marshal.AllocHGlobal(data.Length);
                var unManagedOverlapped = Marshal.AllocHGlobal(Marshal.SizeOf(hidOverlapped));
                Marshal.StructureToPtr(hidOverlapped,
                                       unManagedOverlapped,
                                       false);

                using (var writeHandle = this.GetWriteFileHandle())
                {
                    var numberOfBytesWritten = 0;
                    var success = WriteFile(writeHandle,
                                            ref data[0],
                                            data.Length,
                                            ref numberOfBytesWritten,
                                            unManagedOverlapped);
                    if (!success)
                    {
                        var result = WaitForSingleObject(eventObject,
                                                         100);
                        switch (result)
                        {
                            case WAIT_OBJECT_0:
                                success = true;
                                break;
                            case WAIT_TIMEOUT:
                                CancelIo(writeHandle);
                                break;
                        }
                    }
                }

                Marshal.FreeHGlobal(unManagedOverlapped);
                Marshal.FreeHGlobal(unManagedBuffer);
            }
            catch (Exception ex)
            {
                // TODO add logging and enhance the try/catch-closure to a smaller one
            }
        }

        private Encoding Encoding
        {
            get
            {
                return Encoding.ASCII;
            }
        }

        public string Read()
        {
            var receivedBytes = 0;
            var receiveBuffer = new byte[ReadBufferSize];

            string data;

            try
            {
                var eventObject = CreateEvent(IntPtr.Zero,
                                              false,
                                              false,
                                              String.Empty);
                var hidOverlapped = GetHidOverlapped(eventObject);

                var unManagedBuffer = Marshal.AllocHGlobal(ReadBufferSize);
                var unManagedOverlapped = Marshal.AllocHGlobal(Marshal.SizeOf(hidOverlapped));

                Marshal.StructureToPtr(hidOverlapped,
                                       unManagedOverlapped,
                                       false);

                using (var readHandle = CreateFile(this._devicePathName,
                                                   GENERIC_READ,
                                                   FILE_SHARE_READ /* | FILE_SHARE_WRITE*/,
                                                   IntPtr.Zero,
                                                   OPEN_EXISTING,
                                                   FILE_FLAG_OVERLAPPED,
                                                   0))
                {
                    var success = ReadFile(readHandle,
                                           unManagedBuffer,
                                           receiveBuffer.Length,
                                           ref receivedBytes,
                                           unManagedOverlapped);
                    if (!success)
                    {
                        var result1 = WaitForSingleObject(eventObject,
                                                          300);
                        switch (result1)
                        {
                            case WAIT_OBJECT_0:
                                GetOverlappedResult(readHandle,
                                                    unManagedOverlapped,
                                                    ref receivedBytes,
                                                    false);
                                break;
                            case WAIT_TIMEOUT:
                            default:
                                //CancelIo(_readHandle);
                                break;
                        }
                    }
                }

                if (receivedBytes > 0)
                {
                    Array.Resize(ref receiveBuffer,
                                 receivedBytes);
                    Marshal.Copy(unManagedBuffer,
                                 receiveBuffer,
                                 0,
                                 receivedBytes);
                    data = this.Encoding.GetString(receiveBuffer);
                }
                else
                {
                    data = null;
                }

                Marshal.FreeHGlobal(unManagedOverlapped);
                Marshal.FreeHGlobal(unManagedBuffer);
            }
            catch (Exception ex)
            {
                // TODO add logging and enhance the try/catch-closure to a smaller one
                data = null;
            }

            return data;
        }

        private SafeFileHandle GetWriteFileHandle()
        {
            var writeHandle = CreateFile(this._devicePathName,
                                         GENERIC_WRITE | GENERIC_READ,
                                         FILE_SHARE_READ | FILE_SHARE_WRITE,
                                         IntPtr.Zero,
                                         OPEN_EXISTING,
                                         0,
                                         0);

            return writeHandle;
        }

        private static NativeOverlapped GetHidOverlapped(IntPtr eventObject)
        {
            return new NativeOverlapped
            {
                OffsetLow = 0,
                OffsetHigh = 0,
                EventHandle = eventObject
            };
        }
    }
}

Otherwise there's a solution available (it's VB.NET though)(但我无法判断这是否适用于ZPL / EPL /指纹/ ...打印机)GetPrinter使用PRINTER_INFO_2
还有pinvoke.net available的翻译。

答案 4 :(得分:0)

我使用了与C ++的TCP / IP通信,我能够从打印引擎响应。

相关问题