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

C#实现Zebra ZD421打印机USB连接及ZPL指令发送问题求助

解决C#连接Zebra ZD421打印机发送ZPL指令的方案

方案一:通过Windows打印队列发送ZPL(推荐,无需第三方SDK)

这种方式依赖打印机已安装驱动,直接向打印队列发送原始ZPL指令,兼容性最好,无需处理USB底层通信,适合大多数场景。

实现步骤

  1. 确保Zebra ZD421已正确安装驱动,且在Windows打印队列中可见。
  2. 使用自定义Raw打印辅助类发送ZPL指令,示例代码如下:
using System;
using System.Runtime.InteropServices;
using System.Text;

public static class RawPrinterHelper
{
    [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    private 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)]
    private static extern bool ClosePrinter(IntPtr hPrinter);

    [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    private 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)]
    private static extern bool EndDocPrinter(IntPtr hPrinter);

    [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    private static extern bool StartPagePrinter(IntPtr hPrinter);

    [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    private static extern bool EndPagePrinter(IntPtr hPrinter);

    [DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    private static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, int dwCount, out int dwWritten);

    public static bool SendRawZpl(string printerName, string zplContent)
    {
        IntPtr printerHandle = IntPtr.Zero;
        var docInfo = new DOCINFOA
        {
            pDocName = "ZPL Print Job",
            pDataType = "RAW"
        };

        if (!OpenPrinter(printerName.Normalize(), out printerHandle, IntPtr.Zero))
        {
            return false;
        }

        bool success = false;
        try
        {
            if (StartDocPrinter(printerHandle, 1, docInfo))
            {
                if (StartPagePrinter(printerHandle))
                {
                    byte[] zplBytes = Encoding.UTF8.GetBytes(zplContent);
                    IntPtr bytePtr = Marshal.AllocCoTaskMem(zplBytes.Length);
                    Marshal.Copy(zplBytes, 0, bytePtr, zplBytes.Length);

                    int bytesWritten = 0;
                    success = WritePrinter(printerHandle, bytePtr, zplBytes.Length, out bytesWritten);

                    Marshal.FreeCoTaskMem(bytePtr);
                    EndPagePrinter(printerHandle);
                }
                EndDocPrinter(printerHandle);
            }
        }
        finally
        {
            ClosePrinter(printerHandle);
        }
        return success;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    private class DOCINFOA
    {
        [MarshalAs(UnmanagedType.LPStr)] public string pDocName;
        [MarshalAs(UnmanagedType.LPStr)] public string pOutputFile;
        [MarshalAs(UnmanagedType.LPStr)] public string pDataType;
    }
}

// 使用示例
public static void TestZplSend()
{
    // 替换为你的Zebra打印机名称(可通过System.Management获取)
    string targetPrinter = "Zebra ZD421";
    string testZpl = "^XA^FO20,20^A0N,50,50^FDHello Zebra!^FS^XZ";
    bool isSuccess = RawPrinterHelper.SendRawZpl(targetPrinter, testZpl);
    Console.WriteLine(isSuccess ? "ZPL发送成功" : "ZPL发送失败");
}

说明

  • 该方法通过Windows API直接发送原始ZPL数据,无需第三方依赖,兼容性强。
  • 可结合你已有的System.Management代码获取打印机名称,匹配目标设备。

方案二:使用Usb.Net实现直接USB通信

若必须通过USB底层通信,以下是Usb.Net的正确使用方式(适配.NET Framework/.NET Core):

步骤

  1. 安装NuGet包:Usb.Net、Windows.Devices.Usb(Windows平台专属)。
  2. 确认Zebra ZD421的VID和PID(可通过设备管理器查看,通常Zebra设备VID为0x0A5F,ZD421的PID需自行确认)。
  3. 实例化设备并发送ZPL:
using Usb.Net;
using Usb.Net.Windows;
using System.Threading.Tasks;

public async Task ConnectAndSendZpl(string deviceId)
{
    // 初始化Windows USB设备工厂,填入正确的VID/PID
    var deviceFactory = new WindowsUsbDeviceFactory(
        new FilterDeviceDefinition(vendorId: 0x0A5F, productId: 0x004B)
    );

    // 获取设备接口管理器
    var interfaceManager = await deviceFactory.GetUsbInterfaceManagerAsync(deviceId);
    
    // 打开设备
    await interfaceManager.OpenAsync();

    // 发送ZPL指令(需确认打印机的批量输出端点,通常为0x02)
    byte[] zplBytes = Encoding.UTF8.GetBytes("^XA^FO20,20^A0N,50,50^FDHello Zebra!^FS^XZ");
    await interfaceManager.WriteAsync(zplBytes, 0, zplBytes.Length);

    // 关闭设备
    await interfaceManager.CloseAsync();
}

注意事项

  • 程序需具备USB设备访问权限,部分场景下需以管理员身份运行。
  • 若文档过时,可参考Usb.Net官方仓库的最新示例代码调整实现。

方案三:使用Zebra Legacy SDK(兼容非MAUI项目)

若倾向使用官方SDK,可尝试以下方法规避版本兼容问题:

  1. 下载Zebra Legacy SDK离线包(推荐v2.15.1版本),手动引用SDK中的Zebra.Sdk.Printer.dll、Zebra.Sdk.Comm.dll等文件,而非通过NuGet安装。
  2. 使用以下代码连接打印机并发送ZPL:
using Zebra.Sdk.Comm;
using Zebra.Sdk.Printer;

public void SendZplViaZebraSdk()
{
    Connection usbConnection = new UsbConnection();
    try
    {
        usbConnection.Open();
        ZebraPrinter printer = ZebraPrinterFactory.GetInstance(usbConnection);
        printer.SendCommand("^XA^FO20,20^A0N,50,50^FDHello Zebra!^FS^XZ");
    }
    finally
    {
        usbConnection.Close();
    }
}

说明

  • 若找不到UsbDiscoverer类,直接实例化UsbConnection并调用Open(),SDK会自动检测连接的Zebra USB打印机。
  • 确保项目目标框架与SDK兼容(推荐.NET Framework 4.6.1及以上)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 21:14:56