You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

发送原始ZPL指令打印斑马标签失败:指令被直接输出

Zebra打印机WPF打印ZPL指令不解析问题

开发了一个C# WPF应用,用于通过Zebra打印机打印标签。标签对应的ZPL代码已生成,在记事本、Notepad++等文本编辑器中打印该代码时,标签能正常输出;但在WPF应用中执行相同打印操作时,ZPL指令被直接打印在标签上,而非解析为预期的标签内容。

XAML文件代码

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ZebraTesting"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>

        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>

        <Grid Grid.Row="1">

            <Grid.ColumnDefinitions>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
            </Grid.ColumnDefinitions>


            <Button Content="TEST-1" Name="test1" Click="test1_Click"></Button>

            <Button Grid.Column="1" Content="TEST-2" Name="test2" Click="test2_Click"></Button>


        </Grid>
        
    </Grid>
</Window>

CS文件代码

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Printing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace ZebraTesting
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void test1_Click(object sender, RoutedEventArgs e)
        {
            System.Windows.Controls.PrintDialog prnt = new PrintDialog();
            prnt.PageRangeSelection = PageRangeSelection.AllPages;
            prnt.UserPageRangeEnabled = false;

            Nullable<bool> result = prnt.ShowDialog();

            if (result == true)
            {

                PrintDocument pdoc = new PrintDocument();
                pdoc.PrintPage += ProvideContent;
                pdoc.Print();
            }

        }

        public void ProvideContent(object sender, PrintPageEventArgs e)
        {

            string zpl = "^XA" + Environment.NewLine +
                    "^A0N,23,31^FDAsset ID:^FS" + Environment.NewLine +
                    "^XZ" + Environment.NewLine;

            e.Graphics.DrawString(zpl, new Font("Arial", 10), System.Drawing.Brushes.Black, 0, 0, new StringFormat());

        }


        private void test2_Click(object sender, RoutedEventArgs e)
        {

            System.Windows.Controls.PrintDialog prnt = new PrintDialog();
            prnt.PageRangeSelection = PageRangeSelection.AllPages;
            prnt.UserPageRangeEnabled = false;

            Nullable<bool> result = prnt.ShowDialog();

            if (result == true)
            {

                string zpl = "^XA" + Environment.NewLine +
                    "^A0N,23,31^FDAsset ID:^FS" + Environment.NewLine +
                    "^XZ" + Environment.NewLine;

                var doc = new FlowDocument();
                doc.ColumnWidth = prnt.PrintableAreaWidth;

                Paragraph p = new Paragraph();
                p.Inlines.Add(zpl);
                doc.Blocks.Add(p);
                prnt.PrintDocument(((IDocumentPaginatorSource)doc).DocumentPaginator, "Label A0000001");

                //doc.Blocks.Add(new Paragraph(new Run(zpl)));
                //prnt.PrintDocument(((IDocumentPaginatorSource)doc).DocumentPaginator, "Label A0000001");
                //prnt.PrintDocument((Section)XamlReader.Parse(zpl));                 

            }

        }
    }
}

问题现象

ZPL指令被原样打印,未输出预期文本。
问题截图1
问题截图2


解决方案

你的代码问题在于:用WPF的PrintDialog结合DrawString或FlowDocument打印时,是把ZPL文本当成普通字符串渲染成图像后发送给打印机,而Zebra打印机需要直接接收原始ZPL指令才能解析执行。

可以通过直接向打印机发送原始字节流的方式解决,以下是具体实现:

1. 添加RawPrinterHelper辅助类

这个类用于向打印机发送原始格式的数据:

using System;
using System.Runtime.InteropServices;
using System.Windows;

public class RawPrinterHelper
{
    [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);

    public static bool SendStringToPrinter(string szPrinterName, string szString)
    {
        IntPtr pBytes;
        int dwCount = szString.Length;
        pBytes = Marshal.StringToCoTaskMemAnsi(szString);
        bool success = SendBytesToPrinter(szPrinterName, pBytes, dwCount);
        Marshal.FreeCoTaskMem(pBytes);
        return success;
    }

    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;

        di.pDocName = "ZPL Label";
        di.pDataType = "RAW";

        if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
        {
            if (StartDocPrinter(hPrinter, 1, di))
            {
                if (StartPagePrinter(hPrinter))
                {
                    bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
                    EndPagePrinter(hPrinter);
                }
                EndDocPrinter(hPrinter);
            }
            ClosePrinter(hPrinter);
        }
        if (!bSuccess)
        {
            dwError = Marshal.GetLastWin32Error();
            MessageBox.Show($"打印失败,错误码:{dwError}");
        }
        return bSuccess;
    }
}

2. 修改按钮点击事件

替换原来的test1_Click方法,使用RawPrinterHelper发送ZPL指令:

private void test1_Click(object sender, RoutedEventArgs e)
{
    System.Windows.Controls.PrintDialog prnt = new PrintDialog();
    prnt.PageRangeSelection = PageRangeSelection.AllPages;
    prnt.UserPageRangeEnabled = false;

    if (prnt.ShowDialog() == true)
    {
        string zpl = "^XA" + Environment.NewLine +
                     "^A0N,23,31^FDAsset ID:^FS" + Environment.NewLine +
                     "^XZ" + Environment.NewLine;

        // 获取选中的打印机名称
        string printerName = prnt.PrintQueue.Name;
        RawPrinterHelper.SendStringToPrinter(printerName, zpl);
    }
}

原理说明

记事本等编辑器打印ZPL时,是将文本以RAW格式直接发送给打印机,打印机收到后会直接解析执行ZPL指令;而你的原有WPF代码是将ZPL作为普通文本渲染成图像再发送,打印机只会打印渲染后的文本内容。使用RawPrinterHelper可以直接将ZPL字符串以RAW格式发送到打印机,让Zebra设备正确解析执行指令。

内容的提问来源于stack exchange,提问作者arpit pandya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 16:25:59