c# - 如何使用 C# 通过 USB 将原始 ZPL 发送到 Zebra 打印机

标签 c# usb zpl-ii

我是一名初学者 C# 程序员。我有一个项目需要我通过 USB 将原始命令发送到 Zebra 打印机 LP 2844 并使其工作。我做了很多研究,并试图找出一种方法来做到这一点。我正在使用 http://support.microsoft.com/kb/322091 中的代码,但它没有用。根据我的测试,似乎我已经向打印机发送了命令,但它没有响应和打印。我对此一无所知。有人可以帮帮我吗?

我正在使用按钮直接发送命令

private void button2_Click(object sender, EventArgs e)
{
    string s = "A50,50,0,2,1,1,N,\"9129302\"";

    // 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, s);
        MessageBox.Show("Data sent to printer.");
    }
}

最佳答案

编辑:为了解决您的更新问题,您遇到的问题是您正在使用 SendStringToPrinter 将 ANSI 字符串(空终止)字符串发送到打印机不是打印机所期望的。据官方EPL2 programming guide第 23 页(根据您的示例,这才是您真正在做的,而不是 ZPL)。

Each command line must be terminated with a Line Feed (LF) character (Dec. 10). Most PC based systems send CR/LF when the Enter key is pressed. The Carriage Return (CR) character is ignored by the printer and cannot be used in place of LF.

因此您必须修改 SendStringToPrinter 以在字符串末尾发送 \n 而不是 \0 或者您必须构建自己使用 ASCII 字节数组并自己使用 RawPrinterHelper.SendBytesToPrinter(就像我在下面的原始答案中所做的那样)。

因此,为了修复您发布的简单示例,我们更改了您的函数调用,我们还必须通过发送 P1\n

告诉打印机实际打印
private void button2_Click(object sender, EventArgs e)
{
    string s = "A50,50,0,2,1,1,N,\"9129302\"\n";
    s += "P1\n";

    // Allow the user to select a printer.
    PrintDialog pd = new PrintDialog();
    pd.PrinterSettings = new PrinterSettings();
    if (DialogResult.OK == pd.ShowDialog(this))
    {
        var bytes = Encoding.ASCII.GetBytes(s);
        // Send a printer-specific to the printer.
        RawPrinterHelper.SendBytesToPrinter(pd.PrinterSettings.PrinterName, bytes, bytes.Length);
        MessageBox.Show("Data sent to printer.");
    }
}

//elsewhere
public static class RawPrinterHelper
{
    //(Snip) The rest of the code you already have from http://support.microsoft.com/kb/322091

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


    private static bool SendBytesToPrinter(string szPrinterName, byte[] bytes, Int32 dwCount)
    {
        Int32 dwError = 0, dwWritten = 0;
        IntPtr hPrinter = new IntPtr(0);
        DOCINFOA di = new DOCINFOA();
        bool bSuccess = false;

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


        if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
        {
            if (StartDocPrinter(hPrinter, 1, di))
            {
                if (StartPagePrinter(hPrinter))
                {
                    bSuccess = WritePrinter(hPrinter, bytes, dwCount, out dwWritten);
                    EndPagePrinter(hPrinter);
                }
                EndDocPrinter(hPrinter);
            }
            ClosePrinter(hPrinter);
        }
        if (bSuccess == false)
        {
            dwError = Marshal.GetLastWin32Error();
            throw new Win32Exception(dwError);
        }
        return bSuccess;
    }
}

我使用 Zebra 的旧版 EPL2 语言完成了此操作,但它应该与您需要使用 ZPL 执行的操作非常相似。也许它会让您朝着正确的方向开始。

public class Label
{
    #region Print logic. Taken from http://support.microsoft.com/kb/322091

    //Snip stuff unchanged from the KB example.   

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

    private static bool SendBytesToPrinter(string szPrinterName, byte[] Bytes, Int32 dwCount)
    {
        Int32 dwError = 0, dwWritten = 0;
        IntPtr hPrinter = new IntPtr(0);
        DOCINFOA di = new DOCINFOA();
        bool bSuccess = false;

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


        if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
        {
            if (StartDocPrinter(hPrinter, 1, di))
            {
                if (StartPagePrinter(hPrinter))
                {
                    bSuccess = WritePrinter(hPrinter, Bytes, dwCount, out dwWritten);
                    EndPagePrinter(hPrinter);
                }
                EndDocPrinter(hPrinter);
            }
            ClosePrinter(hPrinter);
        }
        if (bSuccess == false)
        {
            dwError = Marshal.GetLastWin32Error();
            throw new Win32Exception(dwError);
        }
        return bSuccess;
    }
    #endregion

    public byte[] CreateCompleteCommand(bool headerAndFooter)
    {
        List<byte> byteCollection = new List<byte>();

        //Static header content describing the label.
        if (headerAndFooter)
        {
            byteCollection.AddRange(Encoding.ASCII.GetBytes("\nN\n"));
            byteCollection.AddRange(Encoding.ASCII.GetBytes(String.Format("S{0}\n", this.Speed)));
            byteCollection.AddRange(Encoding.ASCII.GetBytes(String.Format("D{0}\n", this.Density)));
            byteCollection.AddRange(Encoding.ASCII.GetBytes(String.Format("q{0}\n", this.LabelHeight)));
            if (this.AdvancedLabelSizing)
            {
                byteCollection.AddRange(Encoding.ASCII.GetBytes(String.Format("Q{0},{1}\n", this.LableLength, this.GapLength)));
            }
        }

        //The content of the label.
        foreach (var command in this.Commands)
        {
            byteCollection.AddRange(command.GenerateByteCommand());
        }

        //The footer content of the label.
        if(headerAndFooter)
            byteCollection.AddRange(Encoding.ASCII.GetBytes(String.Format("P{0}\n", this.Pages)));

        return byteCollection.ToArray();
    }

    public bool PrintLabel(string printer)
    {
        byte[] command = this.CreateCompleteCommand(true);
        return SendBytesToPrinter(printer, command, command.Length); 
    }

    public List<Epl2CommandBase> Commands { get; private set; }

    //Snip rest of the code.
}

public abstract partial class Epl2CommandBase
{
    protected Epl2CommandBase() { }

    public virtual byte[] GenerateByteCommand()
    {
        return Encoding.ASCII.GetBytes(CommandString + '\n');
    }
    public abstract string CommandString { get; set; }
}


public class Text : Epl2CommandBase 
{
    public override string CommandString
    {
        get
        {
            string printText = TextValue;
            if (Font == Fonts.Pts24)
                printText = TextValue.ToUpperInvariant();
            printText = printText.Replace("\\", "\\\\"); // Replace \ with \\
            printText = printText.Replace("\"", "\\\""); // replace " with \"
            return String.Format("A{0},{1},{2},{3},{4},{5},{6},\"{7}\"", X, Y, (byte)TextRotation, (byte)Font, HorziontalMultiplier, VertricalMultiplier, Reverse, printText);
        }
        set
        {
            GenerateCommandFromText(value);
        }
    }

    private void GenerateCommandFromText(string command)
    {
        if (!command.StartsWith(GetFactoryKey()))
            throw new ArgumentException("Command must begin with " + GetFactoryKey());
        string[] commands = command.Substring(1).Split(',');
        this.X = int.Parse(commands[0]);
        this.Y = int.Parse(commands[1]);
        this.TextRotation = (Rotation)byte.Parse(commands[2]);
        this.Font = (Fonts)byte.Parse(commands[3]);
        this.HorziontalMultiplier = int.Parse(commands[4]);
        this.VertricalMultiplier = int.Parse(commands[5]);
        this.ReverseImageColor = commands[6].Trim().ToUpper() == "R";
        string message = String.Join(",", commands, 7, commands.Length - 7);
        this.TextValue = message.Substring(1, message.Length - 2); // Remove the " at the beginning and end of the string.
    }

    //Snip
}

关于c# - 如何使用 C# 通过 USB 将原始 ZPL 发送到 Zebra 打印机,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25669403/

相关文章:

usb - USB设备的多个驱动程序

Linux:如何将 USB 驱动程序分配给设备

zebra-printers - ZPL 设置 GX430t

c# - ASP.NET MVC3 服务层 - 每个服务有多个存储库?

usb - 使用多个 USB 网络摄像头的影响

c# - Zebra EPL/ZPL 上的 .NET 网络套接字打印

c# - 如何通过 ZPL 将 dpi 从 200 更改为 300

c# - MDI 窗口列表不更新子标题栏文本

java - 统一安卓 : Didn't find class "com.unity3d.player.ReflectionHelper"

等效于 VBA 指数形式的 C# 数据类型