Printing "raw text" (ZPL) from Web
Asked Answered
C

3

7

We have a lot of old ZPL labels.

We would like to be able to print them from a web client. The printer is connected to the client and not the server.

We have had a few ideas:

  1. Print from Silverlight. Not feasable. Seems to be no way to print "raw" to Zebra from .NET without calling COM object and that is not posible from plain Silverlight.

  2. From Silverlight, treat the ZPL as file and file copy it to printer. Local printer must be setup as shared. Does work from Silverlight Out of Browser with elevated trust. But if posible we would like to avoid Out of browser.

  3. If Zebra printer is set to use Generic/Text driver, I can open a ZPL-file in Notepad.exe and send ZPL to printer using File -> Print. In this case the Zebra printer will interpret the text as ZPL instructions and not actual text. Is there any way to "exploit" this from a browser? Have tried a few ways, for example to simply open the ZPL file in the browser and the do File -> Print but that does not seem to work. Have also tried to print from Javascript windows.print();

  4. Is there any other plugin (java applet, flash, etc.) capable of sending Raw text (e.g. ZPL) to the Zebra printer?

  5. Transform ZPL to images (or pdf:s). Is there any such tool?

Any other ideas?

Chandelle answered 10/8, 2011 at 9:29 Comment(1)
You can call COM in Out Of Browser (or in browser with some changes in windows registry).Fideism
M
3

In Silverlight 5 you can print raw text when you turn on enhanced security. Here is what I did:

private void Button_Click(object sender, RoutedEventArgs e)
{
    StringBuilder label = new StringBuilder();
    label.AppendLine("^XA^MCA^PR8^XZ");
    label.AppendLine("^XA");
    label.AppendLine("^DFCTN^FS");
    label.AppendLine("^LH110,0^FS");
    label.Append("^FO0,60^A0,30,20^FB250,1,0,C,0^FD");
    label.Append(CategoryTextBox.Text.TrimEnd());
    label.AppendLine("^FS");
    label.AppendLine("^FO5,120^A0,40,30^FB250,1,0,C,0^FR^FN1^FS");
    label.AppendLine("^XZ");
    label.AppendLine("^XA");
    label.AppendLine("^XFCTN^FS");
    label.Append("^FO10,100");
    label.Append("^B3N,N,40,Y^FD");
    label.Append(LicensePlateTextBox.Text.TrimEnd());
    label.AppendLine("^FS");
    label.AppendLine("^XZ");

    bool result = RawPrinterHelper.SendStringToPrinter("Zebra Label Printer", label.ToString());
    if (!result)
    {
        MessageBox.Show("Error Returned From Print Spool.  Check Setup.");
    }
}

The RawPrintHelper class:

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

namespace TestPrinting
{
    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, 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);

        // 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)
        {
            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 = "Document";
            di.pDataType = "RAW";

            // Open the printer.
            if (OpenPrinter(szPrinterName, 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 SendStringToPrinter(string szPrinterName, string pDoc)
        {
            MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(pDoc));
            byte[] rawData = new byte[stream.Length];
            stream.Read(rawData, 0, (int)stream.Length);
            GCHandle rawDataHandle = GCHandle.Alloc(rawData, GCHandleType.Pinned);
            IntPtr pointer = rawDataHandle.AddrOfPinnedObject();
            return SendBytesToPrinter(szPrinterName, pointer, rawData.Length);
        }
    }
}
Maliamalice answered 8/2, 2012 at 21:20 Comment(0)
K
2

If the printer is connected directly to the network, you can open a socket to port 9100 and send the ZPL code there.

Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
    ProtocolType.Tcp);
SocketAsyncEventArgs args = new SocketAsyncEventArgs();
args.RemoteEndPoint = new IPEndPoint("192.168.0.2", 9100);
args.UserToken = sock;
args.Completed += (s,e) => {
    if (e.SocketError == SocketError.Success)
    {
        string zpl = string.Format(
            @"
^XA^MCA^PR8^XZ
^XA
^DFCTN^FS
^LH110,0^FS
^FO0,60^A0,30,20^FB250,1,0,C,0^FD{0}^FS
^FO5,120^A0,40,30^FB250,1,0,C,0^FR^FN1^FS
^XZ
^XA
^XFCTN^FS
^FO10,100^B3N,N,40,Y^FD{1}^FS
^XZ
            ".Trim(),
            category, licencePlate);
        byte[] buf = Encoding.UTF8.GetBytes(zpl);
        e.SetBuffer(buf, 0, buf.Length);
        sock.SendAsync(e);
    }
};

sock.ConnectAsync(args);

Unfortunately, Silverlight only allows socket connections on ports 4502-4534, unless it is run with elevated privileges. You must either run the silverlight application as a trusted application, configure the printer to listen on a safe port, or relay it trough a server.

Kevinkevina answered 2/10, 2011 at 19:53 Comment(3)
If you reconfigure the printer, or relay the connection trough the server, it should be possible.Kevinkevina
Asker says "printer is connected to client and not server".Turfy
@Turfy Yes, on the client. Silverlight can open sockets.Fideism
M
1

You can use this wonderful java applet jZebra http://code.google.com/p/jzebra/ it sends raw data to any printer.

Mendymene answered 6/9, 2011 at 23:38 Comment(1)
it's usually a good idea to put solution here AND provide a link to where you've found it. We do this because linked pages can get expired or deleted.Calista

© 2022 - 2024 — McMap. All rights reserved.