-1

I want to print labels on a printer that includes ZPL.
The printer is connected to USB.
I tried this code using the SendStringToUsbPrinter function as entry point.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;

namespace Core.Helpers  
{
    public class clsUsb
    {
        [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, Int32 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, Int32 dwCount, out Int32 dwWritten);

        public void SendBytesToUsbPrinter(string pPrinterName, IntPtr pBytes, Int32 pCount)
        {
            DOCINFOA doc = new DOCINFOA();
            IntPtr hPrinter = new IntPtr(0);
            Int32 iWritten = 0;

            doc.pDocName = "Document";
            doc.pDataType = "RAW";

            try
            {
                //Ouvre l'acces à l'imprimante
                if (OpenPrinter(pPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
                {
                    //Débute l'impression de document
                    StartDocPrinter(hPrinter, 1, doc);
                    if (StartPagePrinter(hPrinter))
                    {
                        //Ecrit les données
                        WritePrinter(hPrinter, pBytes, pCount, out iWritten);
                        EndPagePrinter(hPrinter);
                    }
                    EndDocPrinter(hPrinter);
                    ClosePrinter(hPrinter);
                }
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
        }

        public void SendStringToUsbPrinter(string pPrinterName, string pData)
        {
            IntPtr pBytes;
            Int32 iCount;

            iCount = pData.Length;
            pBytes = Marshal.StringToCoTaskMemAnsi(pData);
            SendBytesToUsbPrinter(pPrinterName, pBytes, iCount);
            Marshal.FreeCoTaskMem(pBytes);
        }


        public void SendFileToUsbPrinter(string pPrinterName, string pFile)
        {
            //Ouverture du fichier
            FileStream fs = new FileStream(pFile, FileMode.Open);
            //Création du binaire
            BinaryReader br = new BinaryReader(fs);
            //Création d'un tableau d'octets da la longueur du fichier
            Byte[] tab = new byte[fs.Length];
            IntPtr pBytes;
            int iLength;

            iLength = Convert.ToInt32(fs.Length);
            //met le contenu du fichier dans le fichier
            tab = br.ReadBytes(iLength);
            pBytes = Marshal.AllocCoTaskMem(iLength);
            //Copie le tableau
            Marshal.Copy(tab, 0, pBytes, iLength);
            //envoie le tableau à l'impresssion
            SendBytesToUsbPrinter(pPrinterName, pBytes, (uint) iLength);
            //Libère la mémoire
            Marshal.FreeCoTaskMem(pBytes);
        }
    }
}

It worked for a while and then without changing the code, at least it doesn't seem to me, nothing prints anymore.

If in the properties of the printer I activate the spooler, the .SHD and .SPL files are well present, except that the .SPL file remains at 0k.
When I replace the RAW argument by TEXT in the code, I can see the size of this file changing before the ZPL code is printed.
When I disable the printer spooler, I get the same result.

The string send in the input string

^XA\r^PR2\r^A0N,58,58^FO36,40^CI0^FD\rLot :\r^FS\r^A0N,58,58^FO144,40^CI0^FD\r210618-0\n^FS\r^BY2^FO160,104^BCN,64,N,N,N^FD>:\r210618-0\n@\r1\n^FS\r^A0N,58,58^FO180,185^CI0^FD\rSPX4.PACK.BB.NN000\n^FS\r^BY2^FO207,256^BCN,64,N,N,N^FD>:\rSPX4.PACK.BB.NN000\n^FS\r^A0N,58,58^FO35,414^CI28^FH^FD\rCarton n_C3_B8:\r^FS\r^A0N,58,58^FO35,485^CI28^FH^FD\rQuantit_C3_A9:\r^FS\r^A0N,58,58^FO35,345^CI0^FD1er IMEI: \r2\n^FS\r^A0N,58,58^FO308,485^CI0^FD\r5\n^FS\r^A0N,58,58^FO308,414^CI0^FD\r1\n^FS\r^BY3^FO540,380^BEN,102,Y^FD\r3700764701584\n^FS\r^PQ1,0,1,Y\r^XZ\r"

I also tried with the Vanara library which code is quite the same but it's the same.

GSerg
  • 76,472
  • 17
  • 159
  • 346
Seb_H
  • 1
  • Why the Marshal and the pointers? See https://stackoverflow.com/a/36804571/11683. – GSerg Jul 22 '21 at 13:24
  • Most of zebra printers could receive ZPL by simple TCP channel – Leszek Mazur Jul 22 '21 at 14:58
  • You have installed the KB5004945 patch that [breaks Zebra printers](https://supportcommunity.zebra.com/s/article/000021051?language=en_US)? – GSerg Jul 22 '21 at 18:03
  • No I haven't installed it and I'm on Windows8. I'm looking for an update that could cause the same problem – Seb_H Jul 23 '21 at 06:32
  • Did you try my string. Maybe this one is the problem – Seb_H Jul 23 '21 at 07:06
  • because when I try to print the label, it doesn't come out but then if I make the test page it doesn't print either. However, I restart the printer and I reprint the test page without any problem. – Seb_H Jul 23 '21 at 07:13

1 Answers1

0

So, I solved my problem. I went through the Vanara Nugget and simplified my code by doing only one function, and sending an array of bytes.

At the same time, I reinstalled the printer driver.

So far, everything works.

I just did several tests and restructured my code to make it more readable.

Thanks for your help

Seb_H
  • 1