【问题标题】:Send Print job from PuTTY to Zebra ZXP 3 SDK (non.zpl printer)将打印作业从 PuTTY 发送到 Zebra ZXP 3 SDK(非.zpl 打印机)
【发布时间】:2015-02-10 12:45:30
【问题描述】:

我拥有的是一个通过 PuTTY(SSH 客户端)访问的病历数据库。卡片本身只有客户名称、条码格式的记录号(仍确定要使用的条码类型)和客户注册日期。

1) 我们可以为 Zebra 条形码标签打印机或与激光打印机(如 HP 或 Brother)兼容的格式以 RAW 格式将数据输出为 .zpl。 2) ZXP 3 SDK 接受什么输出? 3) SDK 是否可以设置为等待并接受来自 RedMon 之类的命令行的数据?

卡片本身只有打印的数据,没有磁条、智能芯片、层压板或类似的东西。

马哈洛提前。

【问题讨论】:

  • @KenWhite-感谢您提供指导。我对此进行了重大编辑。如果它仍然不正常,你能提供建议吗?我确实想遵守准则,但也承认就问题本身而言有点绝望。
  • 出色的编辑!更清楚你在问什么。 +1,谢谢。 :-)
  • @KenWhite-感谢 Ken 在我遇到此问题时耐心和乐于助人。

标签: c# putty zebra-printers redmon


【解决方案1】:

我不建议使用 RedMon 或 SDK,因为您尝试做的事情都不需要,而且它们都是时间吸血鬼。相反,我会编写一个小型 Windows 窗体应用程序,它侦听 TCP 端口以接收打印作业并将其发送到使用 Zebra 驱动程序的标准打印机。

让 MUMPS 应用程序通过 VT100 中的远程打印支持发送 XML 文档。我一直在使用的示例如下:

^[[5i
<patient>
    <name first="John" last="Smith" />
    <mrn>A04390503</mrn>
    <dob>1991-03-12</dob>
</patient>
^[[4i

在 Windows 客户端上配置打印机以重定向到 TCP/IP:

  1. 添加打印机
  2. 本地打印机
  3. 创建一个新端口
    • 标准 TCP/IP 端口
    • 主机名:127.0.0.1
    • 端口名称:CardFormatter
    • 取消选中“查询打印机并自动选择要使用的驱动程序”
    • 设备类型:自定义
      • 协议:原始
      • 端口:9101
  4. 驱动程序:通用/纯文本

在登录时启动应用程序,然后从服务器打印。 MUMPS 应用程序将返回 XML,Putty 将其打印到文本打印机,然后再发送到本地主机上的 C# 应用程序。 C# 应用程序解释 XML 并通过 Zebra 驱动程序或 SDK 打印到实际打印机。

注意:这仅假定每个工作站有一个交互式会话。如果您使用的是快速用户切换或终端服务,则必须更加小心以确保一切正常。

示例应用:

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace PassThroughPrinterTest
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new TrayApplicationContext());
        }
    }
}

TrayApplicationContext.cs

using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace PassThroughPrinterTest
{
    class TrayApplicationContext : ApplicationContext
    {
        private NotifyIcon trayIcon;
        private PrintListener listener;
        private PrintHandler handler;

        public TrayApplicationContext()
        {
            this.trayIcon = new NotifyIcon()
            {
                Text = "Card Formatter",
                Icon = Properties.Resources.AppIcon,
                ContextMenu = new ContextMenu()
                {
                    MenuItems =
                    {
                        new MenuItem("Print Options...", miPrintOptions_Click),
                        new MenuItem("Exit", miExit_Click)
                    }
                },
                Visible = true
            };

            this.handler = new PrintHandler();

            this.listener = new PrintListener(9101);
            this.listener.PrintDataReceived += this.handler.HandlePrintData;
        }

        private void miPrintOptions_Click(object sender, EventArgs args)
        {
            // TODO: add configuration and options to avoid having to hard code
            // the printer name in PrintHandler.cs
            MessageBox.Show("Options");
        }

        private void miExit_Click(object sender, EventArgs args)
        {
            Application.Exit();
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);

            if (disposing)
            {
                trayIcon.Dispose();
            }
        }
    }
}

PrintHandler.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Printing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml.Linq;

namespace PassThroughPrinterTest
{
    partial class PrintHandler : Form
    {
        public PrintHandler()
        {
            InitializeComponent();
        }

        public void HandlePrintData(object sender, PrintDataReceivedEventArgs args)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new EventHandler<PrintDataReceivedEventArgs>(HandlePrintData), sender, args);
                return;
            }

            this.Show();

            var sXml = Encoding.UTF8.GetString(args.PrintData);
            this.PrintCard(XDocument.Parse(sXml));

            this.Hide();
        }

        private void PrintCard(XDocument xDocument)
        {
            var nameElement = xDocument.Root.Element("name");
            var lastName = nameElement.Attribute("last").Value;
            var firstName = nameElement.Attribute("first").Value;
            var mrn = xDocument.Root.Element("mrn").Value;

            var printDoc = new PrintDocument()
            {
                PrinterSettings = new PrinterSettings()
                {
                    PrinterName = "Adobe PDF"
                },
                DocumentName = "Patient ID Card"
            };
            var cardPaperSize = new PaperSize("Card", 337, 213) { RawKind = (int)PaperKind.Custom };
            printDoc.DefaultPageSettings.PaperSize = cardPaperSize;
            printDoc.PrinterSettings.DefaultPageSettings.PaperSize = cardPaperSize;
            printDoc.PrintPage += (s, e) =>
            {
                var gfx = e.Graphics;

                // print the text information
                var fArial12 = new Font("Arial", 12);
                gfx.DrawString(lastName, fArial12, Brushes.Black, new RectangleF(25, 25, 200, 75));
                gfx.DrawString(firstName, fArial12, Brushes.Black, new RectangleF(25, 100, 200, 75));

                // add a code39 barcode using a barcode font
                // http://www.idautomation.com/free-barcode-products/code39-font/
                // var fCode39 = new Font("IDAutomationHC39M", 12);
                // gfx.DrawString("(" + mrn + ")", fArial12, Brushes.Black, new RectangleF(25, 200, 200, 75));

                // or by using a barcode library
                // https://barcoderender.codeplex.com/
                // var barcode = BarcodeDrawFactory.Code128WithChecksum.Draw(mrn, 20, 2);
                // gfx.DrawImage(barcode, 50, 200);

                e.HasMorePages = false;
            };
            printDoc.Print();
        }
    }
}

PrintListener.cs

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace PassThroughPrinterTest
{
    sealed class PrintListener : IDisposable
    {
        private TcpListener listener;

        public event EventHandler<PrintDataReceivedEventArgs> PrintDataReceived;

        public PrintListener(int port)
        {
            this.listener = new TcpListener(IPAddress.Loopback, port);
            this.listener.Start();

            this.listener.BeginAcceptTcpClient(listener_AcceptClient, null);
        }

        public void Dispose()
        {
            this.listener.Stop();
        }

        private void listener_AcceptClient(IAsyncResult iar)
        {
            TcpClient client = null;
            bool isStopped = false;
            try
            {
                client = this.listener.EndAcceptTcpClient(iar);
            }
            catch (ObjectDisposedException)
            {
                // this will occur in graceful shutdown
                isStopped = true;
                return;
            }
            finally
            {
                if (!isStopped)
                {
                    this.listener.BeginAcceptTcpClient(listener_AcceptClient, null);
                }
            }
            Debug.Assert(client != null);

            try
            {
                byte[] printData;
                using (var clientStream = client.GetStream())
                using (var buffer = new MemoryStream())
                {
                    clientStream.CopyTo(buffer);

                    printData = buffer.ToArray();
                }

                OnPrintDataReceived(printData);
            }
            catch
            {
                // TODO: add logging and error handling for network issues or processing issues
                throw;
            }
            finally
            {
                client.Close();
            }
        }

        private void OnPrintDataReceived(byte[] printData)
        {
            var handler = PrintDataReceived;
            if (handler != null)
            {
                handler(this, new PrintDataReceivedEventArgs(printData));
            }
        }
    }
}

TrayApplicationContext.cs

using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace PassThroughPrinterTest
{
    class TrayApplicationContext : ApplicationContext
    {
        private NotifyIcon trayIcon;
        private PrintListener listener;
        private PrintHandler handler;

        public TrayApplicationContext()
        {
            this.trayIcon = new NotifyIcon()
            {
                Text = "Card Formatter",
                Icon = Properties.Resources.AppIcon,
                ContextMenu = new ContextMenu()
                {
                    MenuItems =
                    {
                        new MenuItem("Print Options...", miPrintOptions_Click),
                        new MenuItem("Exit", miExit_Click)
                    }
                },
                Visible = true
            };

            this.handler = new PrintHandler();

            this.listener = new PrintListener(9101);
            this.listener.PrintDataReceived += this.handler.HandlePrintData;
        }

        private void miPrintOptions_Click(object sender, EventArgs args)
        {
            // TODO: add configuration and options to avoid having to hard code
            // the printer name in PrintHandler.cs
            MessageBox.Show("Options");
        }

        private void miExit_Click(object sender, EventArgs args)
        {
            Application.Exit();
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);

            if (disposing)
            {
                listener.Dispose();
                trayIcon.Dispose();
            }
        }
    }
}

PrintDataReceivedEventArgs.cs

using System;

namespace PassThroughPrinterTest
{
    class PrintDataReceivedEventArgs : EventArgs
    {
        public byte[] PrintData { get; set; }

        public PrintDataReceivedEventArgs(byte[] data)
        {
            if (data == null)
                throw new ArgumentNullException("data");

            this.PrintData = data;
        }
    }
}

【讨论】:

  • @Mitch-我会试一试,看看效果如何。将需要让实际的数据库管理员在他们的最后进行清理。它可能仍然设置为输出 .zpl,因为他们正在等待我找到解决方案(我希望你刚刚提供了)。
  • @Mitch-必须与数据库管理器合作,将这些数据打印为 XML。同时,我从来没有使用过 C#,所以我不确定如何让它在登录时运行,是否有命令行,或者我需要用 Visual Studio 编译它,或者是否有 . exe埋在这里的某个地方?
猜你喜欢
  • 1970-01-01
  • 2011-01-03
  • 1970-01-01
  • 2011-05-25
  • 2021-07-17
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多