2

I am working on building a website that will print ZPL code to a Zebra printer "140XiIII". The specifics are as follows:

  1. The Printer is connected to the computer via Parallel Port.

  2. The Printer is not connected to the network.

  3. Website Administrator wished to avoid Javascript use if at all possible and instead focus on C#.

I have tried using the code at .NET code to send ZPL to Zebra printers that states that it will work on any port. I run through the code and get no errors, but also nothing gets sent to the printer.

I have attempted to decipher and use the InpOut32/64 DLL, though that is more complicated than my meager learnings are able to understand.

Other options either require the printer be connected to the network, or are outdated and no longer an option due to no longer being in the Windows code.

Thank you.

Community
  • 1
  • 1
Ingram Yates
  • 89
  • 1
  • 10
  • the printer is on Client computer or on Host computer?, for print you has tryed send ZPL code or PrintDocument o how you send data to printer? – henoc salinas Feb 20 '18 at 20:12
  • https://stackoverflow.com/questions/2044676/net-code-to-send-zpl-to-zebra-printers – Hans Passant Feb 21 '18 at 16:19
  • have you checked if your ZPL code is correct? There are online ZPL viewers where you can check if your ZPL code is working. I know for a fact that our own Zebra printers don't complain about ZPL errors, they just silently discard the print job. – Dirk Trilsbeek Feb 21 '18 at 16:24
  • @HansPassant I have been attempting those code variations. the first on (11) uses a form that is no longer supported, FileStream. The second one (32) is trying to call forms, which makes me think that it seems to be intended for webforms and not .net. the third option, (System.IO.File.Copy(inputFilePath, printerPath);) is for a shared printer, this one is not shared, or even on the network. Option 4 (9) is currently being shoehorned into the code to try it. the other options are either VB or networked printer options, neither of which are viable for this situation. – Ingram Yates Feb 21 '18 at 17:34
  • @DirkTrilsbeek I will see if i can dig one of those up and check. I'm pulling the code directly from the old method(VB6 code) and may be borking it. – Ingram Yates Feb 21 '18 at 17:35
  • @henocsalinas The printer is hooked to the computer that is viewing the webpage. i believe that makes it client? I am currently trying to figure out how to send the printdoc and ZPL codes to the printer. – Ingram Yates Feb 21 '18 at 17:43
  • @IngramYates if the printers is connected to Client PC, an you need send data in ZPL format, you need create a socket, then install socket on client pc, then on your page send ZPL code, printer name to socket, you canot print directly from page or with code on ServerSide code, isuggest create a socket on a windows service, then add a void with printername parameter and zpl code parameter, then use RAWPrinter to send string to the selected printer. – henoc salinas Feb 21 '18 at 17:58
  • @henocsalinas that would be with any code, be it C# or Javascript, correct? – Ingram Yates Feb 21 '18 at 19:50
  • @IngramYates c# for make the windowsService Socket, Javascript for connect to local port asigned in websocket – henoc salinas Feb 21 '18 at 19:56
  • @IngramYates i post my code for print zpl on clientside – henoc salinas Feb 22 '18 at 02:06
  • @IngramYates Have you tried the code? – henoc salinas Feb 22 '18 at 22:51

3 Answers3

2

I would suggest trying the following:

  • Log into the server, preferably as the user that the service is set to run as.
  • Ensure your Zebra printer is installed as a local printer, and the printer name is correct.
  • Print a test page from the printer properties.
  • Print your ZPL manually:

net use lpt1 "printer shared name" print "C:\Users\serviceuser\desktop\label.txt"

If you try the above and it works, I would be surprised that the code you linked does not work.

Rkand
  • 471
  • 2
  • 9
  • when you say log into the server, you mean use the physical machine that is hosting the website? The Zebra is not attached to the Webserver, could that be part of the issue? – Ingram Yates Feb 21 '18 at 17:45
  • Network shared printers are setup per user in windows. You will have to log in to the account that the service is running as, then install the shared printer to that account. – Rkand Feb 22 '18 at 18:16
  • This answer led us to attempting to send cmd commands to the client printer from the webpage, however no matter where we placed the file to be printed, we could not get it to print via the webpage. printing via manual insertion of the command via the command prompt would allow us to print. – Ingram Yates Feb 26 '18 at 22:35
  • You're not clear. Command prompt worked, but was it from the remote desktop on the server? Or the client? Does the server account that the webservice runs as have the shared printer installed? – Rkand Feb 28 '18 at 00:48
  • Ok, I now see the printer is only available on the client, and not on the server. Yes, the only solution for using ZPL is to pre-load software on the client. – Rkand Feb 28 '18 at 13:34
0

i develop a websockt for this cases ZPLwebSocket

  1. Download the file and uncompress.
  2. Run SetUp.exe on client PC.
  3. Go to services and start 'Servicio de Impresion desde Navegador'
  4. open trysocket.html with GoogleChrome or mozilla
  5. write the name of local printer
  6. click on button 'enviar'
  7. show the messages of server

    this is javascriptcode on page.

    $(document).ready(function () {  var connection = new WebSocket('ws://localhost:2645/service/');  const reader = new FileReader();
    
      $('.sendZPL').on('click', function () {
    
        var tosend = {
          TipoArchivo: 0,
          nombre: "Etiqueta de Prueba",
          code: $(".sendZPL").val(),
          Tipo: 4,
          Impresora: $(".impresora").val()
        }
        connection.send(JSON.stringify(tosend));
      });
    
      connection.addEventListener('message', function (event) {
        reader.readAsText(event.data);
      });
    
      reader.addEventListener('loadend', (e) => {
        const text = e.srcElement.result;
        console.log(text);
        $(".serverResponse").val(text);
      });
    
    });
    

this is the socket code c# for run on ConsoleApp:

class Program
{

    private static Server.WebsocketServer websocketServer;
    private static System.Diagnostics.EventLog eventLog1= new EventLog();
    static void Main( string[] args )
    {
        if (!System.Diagnostics.EventLog.SourceExists( "MySource" ))
        {
            System.Diagnostics.EventLog.CreateEventSource(
                "MySource", "MyNewLog" );
        }

        eventLog1.Source = "MySource";
        eventLog1.Log = "MyNewLog";


        websocketServer = new Server.WebsocketServer();
        websocketServer.LogMessage += WebsocketServer_LogMessage; 

        websocketServer.Start( "http://localhost:2645/tryservice/" );

        Console.Read();
    }



    private static void WebsocketServer_LogMessage( object sender, Server.WebsocketServer.LogMessageEventArgs e )
    {
        // eventLog1.WriteEntry( e.Message );
        Console.ForegroundColor = ConsoleColor.Yellow;
        Console.WriteLine( e.Message );
        Console.ForegroundColor = ConsoleColor.White;
    }
public  class WebsocketServer
{
    public event OnLogMessage LogMessage;
    public delegate void OnLogMessage(Object sender, LogMessageEventArgs e);
    public class LogMessageEventArgs : EventArgs
    {
        public string Message { get; set; }
        public LogMessageEventArgs(string Message) {
            this.Message = Message;
        }
    }

    public bool started = false;
    public async void Start(string httpListenerPrefix)
    {
        HttpListener httpListener = new HttpListener();
        httpListener.Prefixes.Add(httpListenerPrefix);
        httpListener.Start();
        LogMessage(this, new LogMessageEventArgs("Listening..."));
        started = true;

        while (started)
        {
            HttpListenerContext httpListenerContext = await httpListener.GetContextAsync();
            if (httpListenerContext.Request.IsWebSocketRequest)
            {
                ProcessRequest(httpListenerContext);
            }
            else
            {
                httpListenerContext.Response.StatusCode = 400;
                httpListenerContext.Response.Close();
                LogMessage(this, new LogMessageEventArgs("Closed..."));
            }
        }
    }

    public void Stop()
    {
        started = false;
    }

    private List<string> _printers = new List<string>();
    public List<string> Printers { get
        {
            _printers.Clear();
            foreach (string imp in System.Drawing.Printing.PrinterSettings.InstalledPrinters)
            {
                _printers.Add(imp);
            }
            return _printers;
        }
    }

    private async void ProcessRequest(HttpListenerContext httpListenerContext)
    {
        WebSocketContext webSocketContext = null;

        try
        {
            webSocketContext = await httpListenerContext.AcceptWebSocketAsync(subProtocol: null);
            LogMessage(this, new LogMessageEventArgs("Connected"));
        }
        catch (Exception e)
        {
            httpListenerContext.Response.StatusCode = 500;
            httpListenerContext.Response.Close();
            LogMessage(this, new LogMessageEventArgs(String.Format("Exception: {0}", e)));
            return;
        }

        WebSocket webSocket = webSocketContext.WebSocket;
        try
        {


            while (webSocket.State == WebSocketState.Open)
            {

                ArraySegment<Byte> buffer = new ArraySegment<byte>(new Byte[8192]);

                WebSocketReceiveResult result = null;

                using (var ms = new System.IO.MemoryStream())
                {
                    do
                    {
                        result = await webSocket.ReceiveAsync(buffer, CancellationToken.None);
                        ms.Write(buffer.Array, buffer.Offset, result.Count);
                    }
                    while (!result.EndOfMessage);

                    ms.Seek(0, System.IO.SeekOrigin.Begin);

                    if (result.MessageType == WebSocketMessageType.Text)
                    {
                        using (var reader = new System.IO.StreamReader(ms, Encoding.UTF8))
                        {
                            var r = System.Text.Encoding.UTF8.GetString(ms.ToArray());
                            var t = Newtonsoft.Json.JsonConvert.DeserializeObject<Datos>(r);
                            bool valid = true;
                            byte[] toBytes = Encoding.UTF8.GetBytes("Error..."); ;

                            if (t != null)
                            {
                                if (t.Impresora.Trim() == string.Empty)
                                {
                                    var printers = "";
                                    Printers.ForEach(print => {
                                        printers += print + "\n";
                                    });

                                    toBytes = Encoding.UTF8.GetBytes("No se Indicó la Impresora\nLas Impresoras disponibles son:\n" + printers);
                                    valid = false;
                                }
                                else if(!Printers.Contains(t.Impresora))
                                {
                                    var printers = "";
                                    Printers.ForEach(print =>
                                    {
                                        printers += print + "\n";
                                    });

                                    toBytes = Encoding.UTF8.GetBytes("Impresora no valida\nLas Impresoras disponibles son:\n" + printers);
                                    valid = false;
                                }


                                if (t.nombre.Trim() == string.Empty)
                                {
                                    toBytes = Encoding.UTF8.GetBytes("No se Indicó el nombre del Documento");
                                    valid = false;
                                }
                                if (t.code== null)
                                {
                                    toBytes = Encoding.UTF8.GetBytes("No hay datos para enviar a la Impresora");
                                    valid = false;
                                }


                                if (valid && print.RawPrinter.SendStringToPrinter(t.Impresora, t.code, t.nombre))
                                {
                                    LogMessage(this, new LogMessageEventArgs(String.Format("Enviado: {0} => {1} => {2}", t.Impresora, t.nombre, t.code)));
                                    toBytes = Encoding.UTF8.GetBytes("Correcto...");
                                }

                                await webSocket.SendAsync(new ArraySegment<byte>(toBytes, 0, int.Parse(toBytes.Length.ToString())), WebSocketMessageType.Binary, result.EndOfMessage, CancellationToken.None);


                            }
                            else
                            {
                                toBytes = Encoding.UTF8.GetBytes("Error...");
                                await webSocket.SendAsync(new ArraySegment<byte>(toBytes, 0, int.Parse(toBytes.Length.ToString())), WebSocketMessageType.Binary, result.EndOfMessage, CancellationToken.None);
                            }
                        }
                    }
                }
            }
        }
        catch (Exception e)
        {
            LogMessage(this, new LogMessageEventArgs(String.Format("Exception: {0} \nLinea:{1}", e, e.StackTrace)));
        }
        finally
        {
            if (webSocket != null)
                webSocket.Dispose();
        }
    }


}

public class Datos {
    public enum TipoArchivo { zpl, pdf, doc, json, text}
    public string nombre { get; set; }
    public string code { get; set; }
    public TipoArchivo Tipo { get; set; } = TipoArchivo.text;
    public string Impresora { get; set; } = "";
}


}

the RAWPrinterClass link:

 public class RawPrinter
    {
        // 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, ref IntPtr hPriknter, 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, ref Int32 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, Int32 dwCount, string DocName = "")
        {
            Int32 dwError = 0;
            Int32 dwWritten = 0;
            IntPtr hPrinter = new IntPtr(0);
            DOCINFOA di = new DOCINFOA();
            bool bSuccess = false;
            // Assume failure unless you specifically succeed.
            di.pDocName = string.IsNullOrEmpty(DocName) ? "My C#.NET RAW Document" : DocName;
            di.pDataType = "RAW";

            // Open the printer.
            if (OpenPrinter(szPrinterName.Normalize(), ref 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, ref 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 = 0;

            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, string DocName = "")
        {
            IntPtr pBytes = default(IntPtr);
            Int32 dwCount = default(Int32);
            // 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.
            var t= SendBytesToPrinter(szPrinterName, pBytes, dwCount, DocName);
            Marshal.FreeCoTaskMem(pBytes);
            return t;
        }
    }
henoc salinas
  • 1,044
  • 1
  • 9
  • 20
  • This answer is invalid, as we do not have, nor can we hook this printer up to the network. – Ingram Yates Feb 26 '18 at 22:32
  • where is connected the printer? i think you connect the printer on client PC, so, the printer is a local printer on Client Machine, install the service on Client Machine write the name of the local printer on the Client Machine, the service as runing on Client Machine not on Host PC, With this you can print even over the internet, if the service and the printer are installed in the client's machine. – henoc salinas Feb 26 '18 at 22:42
0

what seems to be the correct answer for the specific situation we are looking to cover is that it is not possible to print to our zebra printer given the constraints we are under. Since this printer is NOT connected to the network, we are having to go with a stand-alone desktop app that will do what we need.

Thank you to everyone who assisted and offered their thoughts and ideas.

Ingram Yates
  • 89
  • 1
  • 10