我们有很多旧的ZPL标签。
我们希望能够从web客户端打印它们。打印机连接到客户端而不是服务器。
我们有一些想法:
-
从Silverlight打印。不利用。似乎没有办法在不调用COM对象的情况下从。net打印"原始"到Zebra,这在普通Silverlight中是不可能的。
-
从Silverlight中,将ZPL视为文件并将其文件复制到打印机。本地打印机必须设置为共享。可以在Silverlight Out of Browser中工作,并具有更高的信任度。但如果可能的话,我们希望避免退出浏览器。
-
如果Zebra打印机设置为使用Generic/Text驱动程序,我可以在Notepad.exe中打开ZPL文件,并使用File -> Print将ZPL发送到打印机。在这种情况下,Zebra打印机将把文本解释为ZPL指令而不是实际文本。有没有办法从浏览器"利用"这一点?我尝试了几种方法,例如简单地在浏览器中打开ZPL文件并执行do file -> Print,但这似乎不起作用。也试过从Javascript打印windows.print();
-
是否有其他插件(java applet, flash等)能够发送原始文本(例如ZPL)到Zebra打印机?
-
将ZPL转换为图像(或pdf:s)。有这样的工具吗?
还有其他想法吗?
在Silverlight 5中,当您打开增强的安全性时,您可以打印原始文本。以下是我所做的:
private void Button_Click(object sender, RoutedEventArgs e)
{
StringBuilder label = new StringBuilder();
label.AppendLine("^XA^MCA^PR8^XZ");
label.AppendLine("^XA");
label.AppendLine("^DFCTN^FS");
label.AppendLine("^LH110,0^FS");
label.Append("^FO0,60^A0,30,20^FB250,1,0,C,0^FD");
label.Append(CategoryTextBox.Text.TrimEnd());
label.AppendLine("^FS");
label.AppendLine("^FO5,120^A0,40,30^FB250,1,0,C,0^FR^FN1^FS");
label.AppendLine("^XZ");
label.AppendLine("^XA");
label.AppendLine("^XFCTN^FS");
label.Append("^FO10,100");
label.Append("^B3N,N,40,Y^FD");
label.Append(LicensePlateTextBox.Text.TrimEnd());
label.AppendLine("^FS");
label.AppendLine("^XZ");
bool result = RawPrinterHelper.SendStringToPrinter("Zebra Label Printer", label.ToString());
if (!result)
{
MessageBox.Show("Error Returned From Print Spool. Check Setup.");
}
}
RawPrintHelper类:
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace TestPrinting
{
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 = "Document";
di.pDataType = "RAW";
// Open the printer.
if (OpenPrinter(szPrinterName, 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 SendStringToPrinter(string szPrinterName, string pDoc)
{
MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(pDoc));
byte[] rawData = new byte[stream.Length];
stream.Read(rawData, 0, (int)stream.Length);
GCHandle rawDataHandle = GCHandle.Alloc(rawData, GCHandleType.Pinned);
IntPtr pointer = rawDataHandle.AddrOfPinnedObject();
return SendBytesToPrinter(szPrinterName, pointer, rawData.Length);
}
}
}
如果打印机直接连接到网络,您可以打开一个套接字到9100端口,并在那里发送ZPL代码。
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType.Tcp);
SocketAsyncEventArgs args = new SocketAsyncEventArgs();
args.RemoteEndPoint = new IPEndPoint("192.168.0.2", 9100);
args.UserToken = sock;
args.Completed += (s,e) => {
if (e.SocketError == SocketError.Success)
{
string zpl = string.Format(
@"
^XA^MCA^PR8^XZ
^XA
^DFCTN^FS
^LH110,0^FS
^FO0,60^A0,30,20^FB250,1,0,C,0^FD{0}^FS
^FO5,120^A0,40,30^FB250,1,0,C,0^FR^FN1^FS
^XZ
^XA
^XFCTN^FS
^FO10,100^B3N,N,40,Y^FD{1}^FS
^XZ
".Trim(),
category, licencePlate);
byte[] buf = Encoding.UTF8.GetBytes(zpl);
e.SetBuffer(buf, 0, buf.Length);
sock.SendAsync(e);
}
};
sock.ConnectAsync(args);
不幸的是,Silverlight只允许端口4502-4534上的套接字连接,除非它以更高的权限运行。您必须将silverlight应用程序作为受信任的应用程序运行,将打印机配置为在安全端口上侦听,或者通过服务器进行中继。
您可以使用这个很棒的java applet jZebra http://code.google.com/p/jzebra/它可以向任何打印机发送原始数据