2009-12-04 17 views
9

Tôi đang làm việc trên một dự án mà chúng tôi cần sử dụng Máy in Zebra cho nhãn mã vạch. Chúng tôi đang sử dụng C# và chúng tôi đang thực hiện OK ở mặt in của sự vật, gửi các chuỗi ZPL thô tới máy in (sử dụng winspool.drv).Trạng thái đọc từ Máy in Zebra

Tuy nhiên, chúng tôi cũng cần phải đọc từ máy in và không có may mắn ở đó.

Chúng tôi cần lấy trạng thái từ máy in, là đầu ra cho lệnh ZPL "~ HS", vì vậy chúng tôi có thể biết số lượng nhãn nằm trong bộ nhớ đang chờ để in. EnumJobs() từ winspool.drv chỉ có công việc trên cửa sổ ống, và sau khi chúng được gửi tới máy in, chúng sẽ biến mất khỏi danh sách đó. Nhưng điều đó không có nghĩa là nhãn đã được in, vì máy in có bộ cảm biến vỏ và chỉ in một nhãn mỗi lần và chúng tôi rõ ràng quan tâm đến việc gửi các nhãn cho máy in.

Tôi đã thử một cái gì đó tương tự (sử dụng các cuộc gọi winspool.drv):

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

Nhưng tôi nhận được gì về cuộc gọi ReadPrinter. Tôi thậm chí không biết đây có phải là cách đi đúng đắn không.

Bất kỳ ai đã giải quyết vấn đề này trước đây?

Cảm ơn.

Trả lời

1

Khoảng 15 năm trước, tôi đã viết phần mềm để in qua máy in Zebra.

Vào thời điểm chúng tôi liên lạc với máy in qua RS-232 (chuẩn nối tiếp chuẩn), hoạt động tốt, mọi thông tin đều được trả lại từ máy in một cách kịp thời và chính xác.

Gần đây tôi muốn làm việc với máy in Epson kiểm đếm, và thấy các trình điều khiển máy in windows vụng về và không hiệu quả. Tôi rơi xuống một mức độ và giao tiếp trực tiếp với máy in thông qua GDI, và tất cả mọi thứ làm việc để satisification của tôi.

Tôi nói đưa ra người đàn ông trung gian, nếu bạn thả xuống một cấp độ và giao tiếp trực tiếp với máy in, thay vì giao tiếp thông qua trình điều khiển máy in windows, bạn sẽ có nhiều thành công hơn.

Hy vọng điều này sẽ giúp,

2

Tôi đang gặp phải vấn đề tương tự. Bạn đã quản lý bất cứ điều gì về chủ đề này?

Axe Perez Parra Castro, đây là cách tôi đã làm nó:

-nhận lớp RawPrinterHelper từ đây http://support.microsoft.com/kb/322091

máy in -my (zebra 2030) không hỗ trợ ZPL, vì vậy như xa như tôi biết cách duy nhất là gửi unicode tới số

-I đã tạo danh sách các ký tự tôi cần ví dụ

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

(có được những giá trị từ int en.wikipedia.org/wiki/ASCII)

-compose lệnh - ví dụsb.Append(esc + enq + Convert.ToChar(7).ToString()); (từ hướng dẫn máy in, lệnh < ESC> < ENQ> < 7> sẽ nhận được phiên bản firmware)

-gửi lệnh RawPrinterHelper.SendStringToPrinter(printerName, sb.ToString()); (PrinterName trong trường hợp của tôi là "Zebra TTP 2030")

+1

và đọc? ... đây là câu hỏi tất cả về ... –

+0

@AndreasNiedermair là một vài năm trước, vì vậy tôi không nhớ chi tiết. Vui lòng xem dự án thử nghiệm này có giúp https://www.dropbox.com/s/2h6gj0o08eksbxu/PrintLabel.zip?dl=0 – bfi

1

ReadPrinter sẽ không giúp đỡ trong tình huống này. Nó sẽ đọc lại công việc in bạn đã gửi tới máy in, chứ không phải phản hồi của máy in. Tuy nhiên, vì lợi ích của sự hoàn chỉnh: Để sử dụng ReadPrinter, bạn phải mở máy in lại, bằng cách sử dụng kết hợp "tên máy in - việc id" cú pháp:

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

này sẽ chỉ làm việc nếu công việc 12345 chưa được xóa.


Đối với việc trả lời các câu hỏi, bạn phải sử dụng WriteFile để gửi dữ liệu và ReadFile để có được câu trả lời. Để sử dụng các chức năng này, bạn cần mở máy in với CreateFile. Sau khi bạn đã làm điều đó, phần còn lại là hoàn toàn tầm thường.

Sự cố ở đây là nhận đường dẫn thiết bị phải được chuyển đến CreateFile để mở máy in. Nếu máy in của bạn là một một LPT, đó là đơn giản như "LPT:", nhưng đối với một máy in USB bạn có để có được những đường dần đến device, trông như thế này:

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

Tôi đã tìm thấy một way to obtain this path , nhưng nó chỉ hoạt động nếu bạn chỉ có một máy in được cài đặt. Nếu bạn có nhiều hơn, bạn sẽ cần một mối quan hệ giữa đường dẫn thiết bị và tên máy in mà bạn nhìn thấy trong bảng điều khiển, và mối quan hệ đó là một cái gì đó tôi đã không figured được nêu ra. Tôi đã tạo câu hỏi cho điều đó: Figuring which printer name corresponds to which device ID.

+0

vị trí của 'WriteFile' và' ReadFile' không - tôi không thể tìm thấy chúng trong * winspool .drv * (xem http://msdn.microsoft.com/en-us/library/windows/desktop/dd162861(v=vs.85).aspx) –

+0

bạn có chắc chắn rằng bạn không thể đọc dữ liệu bằng '. ReadPrinter' ?? http://msdn.microsoft.com/en-us/library/windows/desktop/dd162895(v=vs.85).aspx nói: "Hàm ReadPrinter truy xuất dữ liệu từ máy in được chỉ định". –

+1

@AndreasNiedermair Có, nó lấy dữ liệu từ máy in, nhưng đó là dữ liệu bạn tự đặt vào máy in đó (printjob của bạn), không phải máy in dữ liệu có thể tạo ra để phản ứng lại với printjob.'WriteFile' và' ReadFile' là các chức năng Windows mục đích chung hoạt động trên nhiều đối tượng khác nhau bao gồm cả máy in, chúng nằm trong kernel32.dll. – GSerg

0

Nếu bạn có cơ hội để sử dụng kernel32.dll và rời ra usb-lái-bound winspool.srv bạn có thể sử dụng phương pháp vani này:

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) (nhưng tôi không thể nói nếu điều này làm việc với ZPL/EPL/vân tay /...- máy in) sử dụng GetPrinter với PRINTER_INFO_2.
Ngoài ra còn có bản dịch tại pinvoke.net available.

+0

hmmm! là giải pháp không còn khả dụng nữa. loại điển hình của microsoft! – AaA

0

Tôi đã sử dụng giao tiếp TCP/IP với C++ và tôi đã có thể phản hồi từ công cụ in.