2016-04-22 2 views
1

Это мой * .prn файл:Zebra Принтер C# код для печати штрих-код этикетки

 
I8,A,001 Q0001,0 
q831 
rN 
S5 
D10 
ZT 
JF 
O 
R20,0 
f100 
N 
B775,188,2,1,2,6,160,B,"SM00020000" 
X0,199,1,0,200 
P1 

SM00020000 быть штрих-код.

string s = "I8,A,001\n\n\nQ0001,0\nq831\nrN\nS5\nD10\nZT\nJF\nO\nR20,0\nf100\nN\nB775,188,2,1,2,6,160,B,\"SM00020000\",199,1,0,200\nP1\n"; 

PrintDialog pd = new new PrintDialog(); 
pd.PrinterSettings = new System.Drawing.Printing. 
pd.PrinterSettings.PrinterName = "ZDesigner GT800 (EPL)"; 
RawPrinterHelper.SendStringToPrinter(pd.PrinterSettings.PrinterName, s); 

public static bool SendStringToPrinter(string szPrinterName, string szString) 
{ 
    IntPtr pBytes; 
    Int32 dwCount; 
    // How many characters are in the string? 
    dwCount = szString.Length; 
    // Assume that the printer is expecting ANSI text, and then convert 
    // the string to ANSI text. 
    pBytes = Marshal.StringToCoTaskMemAnsi(szString); 
    // Send the converted ANSI string to the printer. 
    SendBytesToPrinter(szPrinterName, pBytes, dwCount); 
    Marshal.FreeCoTaskMem(pBytes); 
    return true; 
} 

public static bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount) 
{ 
    Int32 dwError = 0, dwWritten = 0; 
    IntPtr hPrinter = new IntPtr(0); 
    DOCINFOA di = new DOCINFOA(); 
    bool bSuccess = false; // Assume failure unless you specifically succeed. 

    di.pDocName = "My C#.NET RAW Document"; 
    di.pDataType = "RAW"; 

    // Open the printer. 
    if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero)) 
    { 
     // Start a document. 
     if (StartDocPrinter(hPrinter, 1, di)) 
     { 
      // Start a page. 
      if (StartPagePrinter(hPrinter)) 
      { 
       // Write your bytes. 
       bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten); 
       EndPagePrinter(hPrinter); 

      } 
      EndDocPrinter(hPrinter); 
     } 
     ClosePrinter(hPrinter); 
    } 
    // If you did not succeed, GetLastError may give more information 
    // about why not. 
    if (bSuccess == false) 
    { 
     dwError = Marshal.GetLastWin32Error(); 
    } 
    return bSuccess; 
} 

Этот код не помогает мне печатать мою этикетку. Документ отправляется в очередь печати, но после этого ничего не происходит. Хотя принтер настроен правильно, и я успешно распечатал его с помощью Zebra Designer.

Кроме того, я бы хотел, чтобы приведенный выше код был напечатан 3 ярлыка в одной строке, так как у меня есть носитель, который содержит 3 наклейки в одной строке. Как это можно достичь?

Модель моего принтера - ZDesigner GT800 (EPL).

+0

Вам не нужно 'StringToCoTaskMemAnsi', используйте [' System.Text.Encoding.Ascii.GetBytes'] (https://msdn.microsoft.com/en-us/library/ds4kkd55%28v= vs.110% 29.aspx). Вам также не нужно запускать страницы, вы печатаете необработанные данные печати на принтер, используйте только «StartDocPrinter» и «WritePrinter». – GSerg

+0

«\ n» может быть неоднозначным в зависимости от вашей среды. Принтеры EPL ожидают, что LINEFEED завершит линию, а не CR. Попробуйте поменять местами «\ x0A» (или C# equivilent) – charlesbridge

ответ

2

Вот класс Microsoft для отправки байтов на принтер. Он готов к использованию из коробки:

using System; 
using System.IO; 
using System.Runtime.InteropServices; 

public class RawPrinterHelper 
{ 
    // Structure and API declarions: 
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
    public class DOCINFOA 
    { 
     [MarshalAs(UnmanagedType.LPStr)] 
     public string pDocName; 
     [MarshalAs(UnmanagedType.LPStr)] 
     public string pOutputFile; 
     [MarshalAs(UnmanagedType.LPStr)] 
     public string pDataType; 
    } 
    [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 
    public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd); 

    [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 
    public static extern bool ClosePrinter(IntPtr hPrinter); 

    [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 
    public static extern bool StartDocPrinter(IntPtr hPrinter, int level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di); 

    [DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 
    public static extern bool EndDocPrinter(IntPtr hPrinter); 

    [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 
    public static extern bool StartPagePrinter(IntPtr hPrinter); 

    [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 
    public static extern bool EndPagePrinter(IntPtr hPrinter); 

    [DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 
    public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, int dwCount, out int dwWritten); 

    // SendBytesToPrinter() 
    // When the function is given a printer name and an unmanaged array 
    // of bytes, the function sends those bytes to the print queue. 
    // Returns true on success, false on failure. 
    public static bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, int dwCount) 
    { 
     int dwError = 0, dwWritten = 0; 
     IntPtr hPrinter = new IntPtr(0); 
     DOCINFOA di = new DOCINFOA(); 
     bool bSuccess = false; // Assume failure unless you specifically succeed. 
     di.pDocName = "My C#.NET RAW Document"; 
     di.pDataType = "RAW"; 

     // Open the printer. 
     if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero)) 
     { 
      // Start a document. 
      if (StartDocPrinter(hPrinter, 1, di)) 
      { 
       // Start a page. 
       if (StartPagePrinter(hPrinter)) 
       { 
        // Write your bytes. 
        bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten); 
        EndPagePrinter(hPrinter); 
       } 
       EndDocPrinter(hPrinter); 
      } 
      ClosePrinter(hPrinter); 
     } 
     // If you did not succeed, GetLastError may give more information 
     // about why not. 
     if (bSuccess == false) 
     { 
      dwError = Marshal.GetLastWin32Error(); 
     } 
     return bSuccess; 
    } 

    public static bool SendFileToPrinter(string szPrinterName, string szFileName) 
    { 
     // Open the file. 
     FileStream fs = new FileStream(szFileName, FileMode.Open); 
     // Create a BinaryReader on the file. 
     BinaryReader br = new BinaryReader(fs); 
     // Dim an array of bytes big enough to hold the file's contents. 
     byte[] bytes = new Byte[fs.Length]; 
     bool bSuccess = false; 
     // Your unmanaged pointer. 
     IntPtr pUnmanagedBytes = new IntPtr(0); 
     int nLength; 

     nLength = Convert.ToInt32(fs.Length); 
     // Read the contents of the file into the array. 
     bytes = br.ReadBytes(nLength); 
     // Allocate some unmanaged memory for those bytes. 
     pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength); 
     // Copy the managed byte array into the unmanaged array. 
     Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength); 
     // Send the unmanaged bytes to the printer. 
     bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength); 
     // Free the unmanaged memory that you allocated earlier. 
     Marshal.FreeCoTaskMem(pUnmanagedBytes); 
     return bSuccess; 
    } 

    public static bool SendStringToPrinter(string szPrinterName, string szString) 
    { 
     IntPtr pBytes; 
     int dwCount; 

     // How many characters are in the string? 
     // Fix from Nicholas Piasecki: 
     // dwCount = szString.Length; 
     dwCount = (szString.Length + 1) * Marshal.SystemMaxDBCSCharSize; 

     // Assume that the printer is expecting ANSI text, and then convert 
     // the string to ANSI text. 
     pBytes = Marshal.StringToCoTaskMemAnsi(szString); 
     // Send the converted ANSI string to the printer. 
     SendBytesToPrinter(szPrinterName, pBytes, dwCount); 
     Marshal.FreeCoTaskMem(pBytes); 
     return true; 
    } 
} 

После этого формата запроса ваш ZPL и отправить его к печати Класс:

 StringBuilder ZplBuilder = new StringBuilder(); 

    // Exemple ZPL String 

         ZplBuilder.Append("^XA"); //Start ZPL 
         ZplBuilder.Append("^FO320,42^APN,48,48^FD").Append(DateTime.Now.Date.ToString("dd/MM/yyyy")).Append("^FS"); 
ZplBuilder.Append("^FO0,304^GB720,168,1^FS"); 
ZplBuilder.Append("^FO0,306^GD720,166,1,B,L^FS"); 
ZplBuilder.Append("^FO0,306^GD720,166,1,B,R^FS"); 
ZplBuilder.Append("^XZ"); 
    // End ZPL 

string ZplString = ZplBuilder.ToString(); 

MemoryStream lmemStream = new MemoryStream(); 

StreamWriter lstreamWriter = new StreamWriter(lmemStream); 
lstreamWriter.Write(ZplString); 
lstreamWriter.Flush(); 
lmemStream.Position = 0; 

byte[] byteArray = lmemStream.ToArray(); 

IntPtr cpUnmanagedBytes = new IntPtr(0); 
int cnLength = byteArray.Length; 
cpUnmanagedBytes = Marshal.AllocCoTaskMem(cnLength); 
Marshal.Copy(byteArray, 0, cpUnmanagedBytes, cnLength); 

RawPrinterHelper.SendBytesToPrinter("Intermec PC43d (203 dpi)", cpUnmanagedBytes, cnLength); 
Marshal.FreeCoTaskMem(cpUnmanagedBytes); 

Он отлично работает на Intermec Printec с БФЛ Protocel.

Надеюсь, это поможет.

+0

Этот код идентичен тому, что показывает OP. Кроме того, если это действительно происходит от Microsoft, это огромный позор, потому что это неверно на многих уровнях (плохие объявления API, используя 'StringToCoTaskMemAnsi' и угадывая размер буфера, не соблюдая тот факт, что' WritePrinter' может только частично записывать данные, и вы будете необходимо вызвать его снова, без обработки ошибок и т. д.). Это похоже на код VB6, перенесенный на C# 1: 1. – GSerg

+0

Я просто знаю, что он отлично работает для меня. Мой принтер печатает все, что я хочу в ZPL, с помощью этого метода. – Julien

+0

Thats for ZPL. Пока мой принтер поддерживает EPL. Это будет работать ? –

0

Я бы предложил не изобретать колесо. Посмотрите на сторонние библиотеки, которые уже делают это. Например, ThermalLabel SDK. Это платная библиотека, но все идет хорошо. Вы даже можете найти некоторые свободные/открытые исходники.

+1

Я пробовал использовать его, но так как это не бесплатно. Это дает мне пробные водяные знаки. –

1

Это то, что мы делаем.

namespace SafeHandles 
{ 
    public class PrinterSafeHandle : global::Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid 
    { 
     [DllImport("winspool.drv", CharSet=CharSet.Auto, SetLastError=true)] 
     private static extern bool OpenPrinter(string pPrinterName, out IntPtr phPrinter, IntPtr pDefault); 

     [DllImport("winspool.drv", CharSet=CharSet.Auto, SetLastError=true, ExactSpelling=true)] 
     private static extern bool ClosePrinter(IntPtr hPrinter); 

     public PrinterSafeHandle(string PrinterName) : base(true) 
     { 
      if (!OpenPrinter(PrinterName, out this.handle, IntPtr.Zero)) 
      { 
       throw new System.ComponentModel.Win32Exception(); 
      } 
     } 

     protected override bool ReleaseHandle() 
     { 
      return ClosePrinter(this.handle); 
     } 
    } 
} 
[DllImport("winspool.drv", CharSet=CharSet.Auto, SetLastError=true)] 
private static extern bool WritePrinter (SafeHandles.PrinterSafeHandle hPrinter, [In, MarshalAs(UnmanagedType.LPArray)] byte[] pBuf, int cdBuf, out int pcWritten); 

[DllImport("winspool.drv", CharSet=CharSet.Auto, SetLastError=true)] 
private static extern bool WritePrinter (SafeHandles.PrinterSafeHandle hPrinter, IntPtr pBuf, int cdBuf, out int pcWritten); 

[DllImport("winspool.drv", CharSet=CharSet.Auto, SetLastError=true)] 
private static extern int StartDocPrinter(SafeHandles.PrinterSafeHandle hPrinter, int Level, [In] ref DOC_INFO_1 pDocInfo); 

[DllImport("winspool.drv", CharSet=CharSet.Auto, SetLastError=true)] 
private static extern bool EndDocPrinter (SafeHandles.PrinterSafeHandle hPrinter); 

[DllImport("winspool.drv", CharSet=CharSet.Auto, SetLastError=true)] 
private static extern bool SetJob (SafeHandles.PrinterSafeHandle hPrinter, int JobID, int Level, IntPtr pJob, int Command); 

private const int JOB_CONTROL_PAUSE = 1; 
private const int JOB_CONTROL_DELETE = 5; 

[StructLayout(LayoutKind.Sequential)] 
private struct DOC_INFO_1 
{ 
    [MarshalAs(UnmanagedType.LPTStr)] public string pDocName; 
    [MarshalAs(UnmanagedType.LPTStr)] public string pOutputFile; 
    [MarshalAs(UnmanagedType.LPTStr)] public string pDatatype; 
} 


public static int SendPrinterCommand(string PrinterName, string DocumentName, string Command, bool Suspended = false) 
{ 
    return SendPrinterCommand(null, PrinterName, DocumentName, Command, Suspended); 
} 

public static int SendPrinterCommand(string PrinterName, string DocumentName, string Command, System.Text.Encoding Encoding, bool Suspended = false) 
{ 
    return SendPrinterCommand(null, PrinterName, DocumentName, Command, Encoding, Suspended); 
} 

public static int SendPrinterCommand(string PrinterName, string DocumentName, byte[] Command, bool Suspended = false) 
{ 
    return SendPrinterCommand(null, PrinterName, DocumentName, Command, Suspended); 
} 

public static int SendPrinterCommand(string ServerName, string PrinterName, string DocumentName, string Command, bool Suspended = false) 
{ 
    return SendPrinterCommand(ServerName, PrinterName, DocumentName, Command, System.Text.Encoding.ASCII, Suspended); 
} 

public static int SendPrinterCommand(string ServerName, string PrinterName, string DocumentName, string Command, System.Text.Encoding Encoding, bool Suspended = false) 
{ 
    return SendPrinterCommand(ServerName, PrinterName, DocumentName, Encoding.GetBytes(Command), Suspended); 
} 

public static int SendPrinterCommand(string ServerName, string PrinterName, string DocumentName, byte[] Command, bool Suspended = false) 
{ 
    string FullPrinterPath = string.IsNullOrEmpty(ServerName) ? PrinterName : System.IO.Path.Combine(ServerName, PrinterName); 

    using (var h = new SafeHandles.PrinterSafeHandle(FullPrinterPath)) 
    { 
     var di1 = new DOC_INFO_1() 
     { 
      pDocName = DocumentName, 
      pOutputFile = null, 
      pDatatype = "RAW" 
     }; 

     int job_id = StartDocPrinter(h, 1, ref di1); 
     if (job_id == 0) 
     { 
      throw new System.ComponentModel.Win32Exception(); 
     } 

     if (Suspended) 
     { 
      if (!SetJob(h, job_id, 0, IntPtr.Zero, JOB_CONTROL_PAUSE)) 
      { 
       throw new System.ComponentModel.Win32Exception(); 
      } 
     } 

     try 
     { 
      int total_bytes_written = 0; 

      if (!WritePrinter(h, Command, Command.Length, out total_bytes_written)) 
      { 
       throw new System.ComponentModel.Win32Exception(); 
      } 

      if (total_bytes_written < Command.Length) 
      { 
       var gch = GCHandle.Alloc(Command, GCHandleType.Pinned); 

       try 
       { 
        do 
        { 
         int next_index = total_bytes_written; 
         int next_requred_len = Command.Length - next_index; 
         int bytes_written_this_time = 0; 

         if (!WritePrinter(h, Marshal.UnsafeAddrOfPinnedArrayElement(Command, next_index), next_requred_len, out bytes_written_this_time)) 
         { 
          throw new System.ComponentModel.Win32Exception(); 
         } 

         total_bytes_written += bytes_written_this_time; 
        } while (total_bytes_written < Command.Length); 
       } 
       finally 
       { 
        gch.Free(); 
       } 
      } 
     } 
     catch 
     { 
      SetJob(h, job_id, 0, IntPtr.Zero, JOB_CONTROL_DELETE); 
      throw; 
     } 
     finally 
     { 
      EndDocPrinter(h); 
     } 

     return job_id; 
    } 

} 
string s = "I8,A,001\n\n\nQ0001,0\nq831\nrN\nS5\nD10\nZT\nJF\nO\nR20,0\nf100\nN\nB775,188,2,1,2,6,160,B,\"SM00020000\",199,1,0,200\nP1\n"; 

SendPrinterCommand("ZDesigner GT800 (EPL)", "Foo", s); 
0

Если какой-либо из них не работает, вы можете написать ZPL команды в файл с помощью C# и непосредственно скопировать его на принтер, если он совместно в сети ,

public void Print(int numCopies = 1) 
    { 

     int randomInt = (new Random()).Next(1000); //this random value is intented to get the collision change of prn file names reduced 
     string SERVERPATH = Path.Combine(System.Web.HttpContext.Current.Server.MapPath("~/PrintOperations/")); 

     if (!Directory.Exists(SERVERPATH)) 
     { 
      Directory.CreateDirectory(SERVERPATH); 

     } 
     String prnFilePath = SERVERPATH + MethodName + randomInt + ".prn"; 
     String fullPrinterPath = @"\\"[email protected]"\"+ printerName; 
     var createdFile = System.IO.File.Create(prnFilePath); 
     createdFile.Close(); 
     System.IO.File.WriteAllText(prnFilePath, parsedZpl); 
     System.Diagnostics.Process process = new System.Diagnostics.Process(); 
     System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(); 
     startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; 
     startInfo.FileName = "cmd.exe"; 
     startInfo.Arguments = string.Format("/C Copy \"{0}\" \"{1}\"", prnFilePath ,fullPrinterPath); 
     process.StartInfo = startInfo; 
     for (int i =0; i< numCopies; i++) 
     { 
      process.Start(); 
      process.WaitForExit(); 

     } 

     System.IO.File.Delete(prnFilePath); 
}