通过 USB 将原始 ZPL 发送到 Zebra 打印机

发布于 2024-10-07 06:42:37 字数 151 浏览 0 评论 0原文

通常,当我将 Zebra LP 2844-Z 插入 USB 端口时,计算机会将其视为打印机,并且我可以像任何其他通用打印机一样从记事本进行打印。但是,我的应用程序具有一些条形码功能。我的应用程序解析一些输入并生成内存中的 ZPL 字符串。我如何将此 ZPL 数据发送到我的 USB 设备?

Typically, when I plug in my Zebra LP 2844-Z to the USB port, the computer sees it as a printer and I can print to it from notepad like any other generic printer. However, my application has some bar code features. My application parses some input and generates an in-memory string of ZPL. How would I send this ZPL data to my USB device?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

千柳 2024-10-14 06:42:37

我找到了答案......或者至少是最简单的答案(如果有多个)。当我安装打印机时,我将其重命名为“ICS 标签打印机”。以下是如何更改选项以允许传递 ZPL 命令:

  1. 右键单击​​“ICS 标签打印机”并选择“属性”。
  2. 在“常规”选项卡上,单击“打印首选项...”按钮。
  3. 在“高级设置”选项卡上,单击“其他”按钮。
  4. 确保选中标有“启用直通模式”的框。
  5. 确保“开始序列:”为“${”。
  6. 确保“结束序列:”为“}$”。
  7. 单击“关闭”按钮。
  8. 单击“确定”按钮。
  9. 单击“确定”按钮。

在我的代码中,我只需将“${”添加到 ZPL 的开头,将“}$”添加到末尾并将其打印为纯文本。这是与“ZDesigner LP 2844-Z 打印机版本 2.6.42(Build 2382)的 Windows 驱动程序”一起使用的。效果就像一个魅力!

I found the answer... or at least, the easiest answer (if there are multiple). When I installed the printer, I renamed it to "ICS Label Printer". Here's how to change the options to allow pass-through ZPL commands:

  1. Right-click on the "ICS Label Printer" and choose "Properties".
  2. On the "General" tab, click on the "Printing Preferences..." button.
  3. On the "Advanced Setup" tab, click on the "Other" button.
  4. Make sure there is a check in the box labeled "Enable Passthrough Mode".
  5. Make sure the "Start sequence:" is "${".
  6. Make sure the "End sequence:" is "}$".
  7. Click on the "Close" button.
  8. Click on the "OK" button.
  9. Click on the "OK" button.

In my code, I just have to add "${" to the beginning of my ZPL and "}$" to the end and print it as plain text. This is with the "Windows driver for ZDesigner LP 2844-Z printer Version 2.6.42 (Build 2382)". Works like a charm!

找回味觉 2024-10-14 06:42:37

我发现了一种通过 COM 端口向 Zebra 打印机写入数据的更简单方法。我转到 Windows 控制面板并添加了一台新打印机。对于端口,我选择 COM1(打印机插入的端口)。我使用了“通用/纯文本”打印机驱动程序。我禁用了后台打印程序(打印机首选项中的标准选项)以及所有高级打印选项。现在,我可以将任何字符串打印到该打印机,如果该字符串包含 ZPL,则打印机可以很好地呈现 ZPL!不需要特殊的“开始序列”或类似的时髦东西。为简单而欢呼!

I've found yet an easier way to write to a Zebra printer over a COM port. I went to the Windows control panel and added a new printer. For the port, I chose COM1 (the port the printer was plugged in to). I used a "Generic / Text Only" printer driver. I disabled the print spooler (a standard option in the printer preferences) as well as all advanced printing options. Now, I can just print any string to that printer and if the string contains ZPL, the printer renders the ZPL just fine! No need for special "start sequences" or funky stuff like that. Yay for simplicity!

等待我真够勒 2024-10-14 06:42:37

Visual Studio C# 解决方案(位于 http://support.microsoft.com/kb /322091)

步骤 1.) 创建类 RawPrinterHelper...

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, 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 = "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;
        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;
    }
}

步骤 2.) 创建一个包含文本框和按钮的表单(文本框将保存 ZPL在此示例中发送)。在按钮单击事件中添加代码...

private void button1_Click(object sender, EventArgs e)
        {
            // Allow the user to select a printer.
            PrintDialog pd = new PrintDialog();
            pd.PrinterSettings = new PrinterSettings();
            if (DialogResult.OK == pd.ShowDialog(this))
            {
                // Send a printer-specific to the printer.
                RawPrinterHelper.SendStringToPrinter(pd.PrinterSettings.PrinterName, textBox1.Text);
                MessageBox.Show("Data sent to printer.");
            }
            else
            {
                MessageBox.Show("Data not sent to printer.");
            }
        }

使用此解决方案,您可以进行调整以满足特定要求。也许对特定打印机进行硬编码。也许可以动态地而不是从文本框导出 ZPL 文本。任何。也许您不需要图形界面,但这显示了如何发送 ZPL。您的使用取决于您的需求。

Visual Studio C# solution (found at http://support.microsoft.com/kb/322091)

Step 1.) Create class RawPrinterHelper...

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, 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 = "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;
        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;
    }
}

Step 2.) Create a form with text box and button (text box will hold the ZPL to send in this example). In button click event add code...

private void button1_Click(object sender, EventArgs e)
        {
            // Allow the user to select a printer.
            PrintDialog pd = new PrintDialog();
            pd.PrinterSettings = new PrinterSettings();
            if (DialogResult.OK == pd.ShowDialog(this))
            {
                // Send a printer-specific to the printer.
                RawPrinterHelper.SendStringToPrinter(pd.PrinterSettings.PrinterName, textBox1.Text);
                MessageBox.Show("Data sent to printer.");
            }
            else
            {
                MessageBox.Show("Data not sent to printer.");
            }
        }

With this solution, you can tweak to meet specific requirements. Perhaps hardcode the specific printer. Perhaps derive the ZPL text dynamically rather than from a text box. Whatever. Perhaps you don't need a graphical interface, but this shows how to send the ZPL. Your use depends on your needs.

妥活 2024-10-14 06:42:37

您还没有提到一种语言,所以我将为您提供一些如何使用 C 语言中的直接 Windows API 来完成此操作的提示。

首先,使用 OpenPrinter。接下来,使用 StartDocPrinter 具有 pDatatype 字段DOC_INFO_1 结构设置为“RAW” - 这告诉打印机驱动程序不要对发送到打印机的任何内容进行编码,而是将其原封不动地传递。使用StartPagePrinter表示第一页,WritePrinter将数据发送到打印机,使用EndPagePrinterEndDocPrinter关闭code> 和 ClosePrinter 完成后。

You haven't mentioned a language, so I'm going to give you some some hints how to do it with the straight Windows API in C.

First, open a connection to the printer with OpenPrinter. Next, start a document with StartDocPrinter having the pDatatype field of the DOC_INFO_1 structure set to "RAW" - this tells the printer driver not to encode anything going to the printer, but to pass it along unchanged. Use StartPagePrinter to indicate the first page, WritePrinter to send the data to the printer, and close it with EndPagePrinter, EndDocPrinter and ClosePrinter when done.

死开点丶别碍眼 2024-10-14 06:42:37

ZPL 是正确的方法。在大多数情况下,使用抽象为 GDI 命令的驱动程序是正确的;然而,Zebra 标签打印机是一个特例。使用 Zebra 打印机进行打印的最佳方法是直接生成 ZPL。请注意,Zebra 打印机的实际打印机驱动程序是“纯文本”打印机 - 不存在可以更新或更改的“驱动程序”,就像我们认为大多数打印机都有驱动程序一样。它只是绝对简约意义上的驱动程序。

ZPL is the correct way to go. In most cases it is correct to use a driver that abstracts to GDI commands; however Zebra label printers are a special case. The best way to print to a Zebra printer is to generate ZPL directly. Note that the actual printer driver for a Zebra printer is a "plain text" printer - there is not a "driver" that could be updated or changed in the sense we think of most printers having drivers. It's just a driver in the absolute minimalist sense.

温折酒 2024-10-14 06:42:37

安装共享打印机:\localhost\zebra
以文本形式发送 ZPL,首先尝试复制:

复制 file.zpl \localhost\zebra

非常简单,几乎不需要编码。

Install an share your printer: \localhost\zebra
Send ZPL as text, try with copy first:

copy file.zpl \localhost\zebra

very simple, almost no coding.

南风几经秋 2024-10-14 06:42:37

对于 2021 年因上述问题折磨自己的人来说,如果您身处 .NET 世界,那么请使用 RawPrint< /a> NuGet 包。

从那里绕过驱动程序直接将 ZPL 字符串打印到打印机,它是:

 IPrinter printer = new Printer();
 printer.PrintRawStream(@"Your Printer Name", GenerateStreamFromString(yourZplString), @"docname");

For anybody torturing themselves with the above in 2021, if you're in the .NET world then get hold of the RawPrint NuGet package.

From there to print your ZPL string directly to the printer, bypassing drivers, it's:

 IPrinter printer = new Printer();
 printer.PrintRawStream(@"Your Printer Name", GenerateStreamFromString(yourZplString), @"docname");
七堇年 2024-10-14 06:42:37

找到了惊人的简单解决方案 - 适用于 Chrome(Windows,未在 Mac 上测试)

Zebra ZP 450

  1. 转到此处 Zebra Generic Text
  2. 严格按照手册进行操作
  3. 不需要 COM1 或任何其他端口 - USB 就足够了
  4. 完成后(将打印机命名为 ZTEXT),即使不打印测试页也没关系
  5. 关闭假脱机功能并在打印机首选项中启用直接打印 - 请注意,1 台打印机仅是 ZP450 CPT 和其他 ZP450 - 在另一台打印机上,我什至不需要关闭假脱机功能,它就可以工作。
  6. 转到 Chrome 并通过选择 ZTEXT 打印机(通用/文本)打印机(不要选择 Windows 对话框),使用 Chrome 打印对话框从那里打印 ZPL - 我们需要这个才能使 Chrome 正常工作

Found amazing simple solution - working for Chrome (Windows, not tested on Mac)

Zebra ZP 450

  1. Go here Zebra Generic Text
  2. Go precisely by the manual
  3. No COM1 or any other ports needed - USB is enough
  4. When done (named the printer ZTEXT), does not matter if it won't print a test page
  5. Turn of Spooling and enable direct printing in Printer Preferences - 1 note here 1 printer is ZP450 CPT and other ZP450 only - on the other one I do not even need to turn off spooling and it worked.
  6. Go to Chrome and printing ZPL from there with Chrome Print Dialog Box by selecting the ZTEXT printer (Generic / Text) Printer (Do not choose Windows Dialog Box) - we needed this for Chrome to be working
缺⑴份安定 2024-10-14 06:42:37

我花了8个小时才做到这一点。
很简单...

您应该有这样的代码:

private const int GENERIC_WRITE = 0x40000000;

//private const int OPEN_EXISTING = 3;
private const int OPEN_EXISTING = 1;
private const int FILE_SHARE_WRITE = 0x2;
private StreamWriter _fileWriter;
private FileStream _outFile;
private int _hPort;

将该变量内容从 3(打开的文件已存在)更改为 1(创建一个新文件)。
它适用于 Windows 7 和 XP。

I spent 8 hours to do that.
It is simple...

You shoud have a code like that:

private const int GENERIC_WRITE = 0x40000000;

//private const int OPEN_EXISTING = 3;
private const int OPEN_EXISTING = 1;
private const int FILE_SHARE_WRITE = 0x2;
private StreamWriter _fileWriter;
private FileStream _outFile;
private int _hPort;

Change that variable content from 3 (open file already exist) to 1 (create a new file).
It'll work at Windows 7 and XP.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文