2009-12-04 322 views
9

我正在开发一个项目,我们需要使用斑马打印机来打印条形码标签。 我们使用C#,并且我们在事物的打印方面做得很好,将原始ZPL字符串发送到打印机(使用winspool.drv)。Zebra打印机的阅读状态

但是,我们还需要从打印机读取数据,并且没有运气。

我们需要从打印机获得状态,这是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调用什么。我甚至不知道这是否正确。

以前有人解决过这个问题吗?

谢谢。

回答

1

大约15年前,我写了软件通过斑马打印机打印。

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

最近我想与爱普生理货打印机合作,并发现Windows打印机驱动程序笨拙和效率低下。我下降了一级并通过GDI直接与打印机进行了沟通,一切都达到了我的满意程度。

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

希望这会有帮助,

2

我正面临同样的问题。你有没有在这个问题上管理过任何东西?

斧佩雷斯帕拉卡斯特罗,这是我做的:

-get的RawPrinterHelper类从这里http://support.microsoft.com/kb/322091

- 我的打印机(斑马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)

-compose命令 - 例如sb.Append(esc + enq + Convert.ToChar(7).ToString());(从打印机手册,命令< ESC> < ENQ> < 7>应该得到的固件版本)

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

+1

和阅读? ...这就是这个问题的全部... – 2014-10-01 06:39:08

+0

@AndreasNiedermair它是几年前,所以我不记得细节。请看看这个实验项目是否有帮助https://www.dropbox.com/s/2h6gj0o08eksbxu/PrintLabel.zip?dl=0 – bfi 2014-10-02 11:55:44

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

+0

“WriteFile”和“ReadFile”位于哪里 - 我在* winspool中找不到它们.drv *(请参阅http://msdn.microsoft.com/en-us/library/windows/desktop/dd162861(v=vs.85).aspx) – 2014-10-01 06:44:16

+0

您确定无法使用'读取数据。 ReadPrinter'? http://msdn.microsoft.com/en-us/library/windows/desktop/dd162895(v=vs.85).aspx说:“ReadPrinter函数从指定的打印机检索数据。” – 2014-10-01 06:46:04

+1

@AndreasNiedermair是的,它从打印机中检索数据,但它是您自己(打印作业)放入打印机的数据,而不是数据打印机可能为打印作业而生成的数据。'WriteFile'和'ReadFile'是通用Windows函数,可用于包括打印机在内的许多不同对象,它们位于kernel32.dll中。 – GSerg 2014-10-01 07:29:58

0

如果你必须使用kernel32.dll并留下了机会,将USB驱动器绑定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/fingerprint /...-打印机),其使用GetPrinterPRINTER_INFO_2
还有一个翻译pinvoke.net available

+0

嗯!作为不再可用的解决方案。微软的典型类型! – AaA 2018-03-09 13:01:29

0

我已经使用C++与TCP/IP通信,并且能够响应打印引擎。