Envoyer le ZPL brut à l'imprimante Zebra via USB
typiquement, quand je branche mon Zebra LP 2844-Z sur le port USB, l'ordinateur le voit comme une imprimante et je peux l'imprimer à partir de bloc-notes comme n'importe quelle autre imprimante générique. Cependant, ma demande comporte des caractéristiques de code à barres. Mon application analyse quelques entrées et génère une chaîne de caractères en mémoire de ZPL. Comment envoyer ces données ZPL à mon périphérique USB?
8 réponses
j'ai trouvé la réponse... ou du moins, la réponse la plus facile (s'il y en a plusieurs). Lorsque j'ai installé l'imprimante, je l'ai renommée "ICS Label Printer". Voici comment modifier les options pour permettre les commandes pass-through ZPL:
- cliquez avec le bouton droit de la souris sur "Imprimante D'étiquettes ICS" et choisissez "Propriétés".
- Sur l'onglet "Général", cliquez sur "Préférences d'Impression..." bouton.
- dans l'onglet" Installation avancée", cliquez sur le bouton" Autre".
- assurez-vous que il y a une case à cocher dans la case intitulée "activer le Mode Passthrough".
- assurez-vous que la" séquence de démarrage: "est" ${".
- assurez-vous que la "séquence de fin:" est "}$".
- Cliquez sur le bouton "Fermer".
- cliquez sur le bouton" OK".
- cliquez sur le bouton" OK".
dans mon code, je dois juste ajouter " $ {"au début de mon ZPL et "}$" à la fin et l'imprimer en clair. C'est avec le "pilote Windows pour ZDesigner LP 2844-Z printer Version 2.6.42 (Build 2382)". Fonctionne comme un charme!
j'ai trouvé un moyen plus simple d'écrire à une imprimante zèbre sur un port COM. Je suis allé dans le panneau de configuration et ajout d'une nouvelle imprimante. Pour le port, J'ai choisi COM1 (le port sur lequel l'imprimante était branchée). J'ai utilisé un "Générique / Texte Seulement" du pilote d'imprimante. J'ai désactivé le spooler d'impression (une option standard dans les préférences d'imprimante) ainsi que toutes les options d'impression avancées. Maintenant, je peux imprimer n'importe quelle chaîne sur cette imprimante et si la chaîne contient ZPL, l'imprimante rend le ZPL parfait! Pas besoin de séquences de démarrage spéciales ou de trucs funky comme ça. Yay pour la simplicité!
Visual Studio C # solution (trouvé à http://support.microsoft.com/kb/322091)
Étape 1.) créer la classe RawPrinterHelper...
using System;
using System.IO;
using System.Runtime.InteropServices;
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 = "My C#.NET RAW Document";
di.pDataType = "RAW";
// Open the printer.
if (OpenPrinter(szPrinterName.Normalize(), 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 SendFileToPrinter(string szPrinterName, string szFileName)
{
// Open the file.
FileStream fs = new FileStream(szFileName, FileMode.Open);
// Create a BinaryReader on the file.
BinaryReader br = new BinaryReader(fs);
// Dim an array of bytes big enough to hold the file's contents.
Byte[] bytes = new Byte[fs.Length];
bool bSuccess = false;
// Your unmanaged pointer.
IntPtr pUnmanagedBytes = new IntPtr(0);
int nLength;
nLength = Convert.ToInt32(fs.Length);
// Read the contents of the file into the array.
bytes = br.ReadBytes(nLength);
// Allocate some unmanaged memory for those bytes.
pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength);
// Copy the managed byte array into the unmanaged array.
Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength);
// Send the unmanaged bytes to the printer.
bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength);
// Free the unmanaged memory that you allocated earlier.
Marshal.FreeCoTaskMem(pUnmanagedBytes);
return bSuccess;
}
public static bool SendStringToPrinter(string szPrinterName, string szString)
{
IntPtr pBytes;
Int32 dwCount;
// How many characters are in the string?
dwCount = szString.Length;
// Assume that the printer is expecting ANSI text, and then convert
// the string to ANSI text.
pBytes = Marshal.StringToCoTaskMemAnsi(szString);
// Send the converted ANSI string to the printer.
SendBytesToPrinter(szPrinterName, pBytes, dwCount);
Marshal.FreeCoTaskMem(pBytes);
return true;
}
}
Étape 2.) créer un formulaire avec la boîte de texte et le bouton (la boîte de texte tiendra le ZPL pour envoyer cet exemple). Dans le bouton Ajouter le code d'événement...
private void button1_Click(object sender, EventArgs e)
{
// 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, textBox1.Text);
MessageBox.Show("Data sent to printer.");
}
else
{
MessageBox.Show("Data not sent to printer.");
}
}
Avec cette solution, vous pouvez personnaliser pour répondre à des exigences spécifiques. Peut-être coder en dur spécifiques imprimante. Peut-être dériver le texte ZPL dynamiquement plutôt que d'une boîte de texte. Quoi. Peut-être que vous n'avez pas besoin d'une interface graphique, mais cela montre comment envoyer le ZPL. Votre utilisation dépend de vos besoins.
vous n'avez pas mentionné de langage, donc je vais vous donner quelques conseils pour le faire avec L'API Windows en C.
tout d'Abord, d'ouvrir une connexion à l'imprimante avec OpenPrinter
. Ensuite, commencez un document avec StartDocPrinter
pDatatype
champ DOC_INFO_1
mise en place de la structure "RAW"
- Ceci indique au pilote d'imprimante de ne pas encoder quoi que ce soit allant à l'imprimante, mais de le transmettre inchangé. Utilisez StartPagePrinter
pour indiquer la première page, WritePrinter
pour envoyer les données à l'imprimante et fermez-la avec EndPagePrinter
,EndDocPrinter
et ClosePrinter
quand c'est fait.
ZPL est la bonne façon de procéder. Dans la plupart des cas, il est correct d'utiliser un pilote qui résume les commandes GDI; toutefois, les imprimantes d'étiquettes Zebra constituent un cas particulier. La meilleure façon d'imprimer sur une imprimante Zebra est de générer ZPL directement. Notez que le pilote d'imprimante réel pour une imprimante Zebra est une imprimante "en texte clair" - il n'y a pas de" pilote " qui pourrait être mis à jour ou modifié dans le sens où nous pensons que la plupart des imprimantes ont des pilotes. C'est juste un pilote au sens minimaliste absolu.
Vous devriez avoir un code comme ça:
private const int GENERIC_WRITE = 0x40000000;
//private const int OPEN_EXISTING = 3;
private const int OPEN_EXISTING = 1;
private const int FILE_SHARE_WRITE = 0x2;
private StreamWriter _fileWriter;
private FileStream _outFile;
private int _hPort;
changer le contenu variable de 3 (Ouvrir le fichier existe déjà) à 1 (Créer un nouveau fichier). Ça marchera sur Windows 7 et XP.
installez un partage de votre imprimante: \localhost\zebra Envoyer ZPL en tant que texte, essayez de copier d'abord:
copier le fichier.zpl \localhost\zebra
très simple, presque pas de codage.
vous pouvez utiliser COM, ou P/Invoke from .Net, pour ouvrir Winspool.DRV pilote et envoyer des octets directement aux périphériques. Mais vous ne voulez pas faire cela; cela ne fonctionne généralement que pour le seul appareil sur la seule version du pilote avec lequel vous testez, et casse sur tout le reste. Prenez ceci à partir d'une longue, douloureuse, expérience personnelle.
ce que vous voulez faire est d'obtenir une police de code à barres ou une bibliothèque qui dessine des codes à barres en utilisant de vieilles commandes simples GDI ou GDI+; Il y en a une pour .Net ici. Cela fonctionne sur tous les appareils, même après Zebra change le pilote.