lunes, 8 de julio de 2013

Imprimir en impresora de etiquetas SATO desde PowerShell

Aquí les dejo un pequeño programa que me habilita la impresión desde PowerShell en impresoras de etiquetas SATO. (parte del código salio de http://social.msdn.microsoft.com/Forums/en-US/94967169-a9ee-45db-9c8a-acd6f173680d/rawprinthelper-for-bold-font)...

El archivo PrinterHelper.ps1 es

clear

$src = @'
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;
 }

 #region "Imports"
  [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);
 #endregion


 public  RawPrinterHelper(){}

 // 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  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 document";
  di.pDataType = "RAW";

  try
  {
   // 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);
   }
  }
  catch (Exception ex)
  {
   throw (ex);
  }
  // If you did not succeed, GetLastError may give more information
  // about why not.
  if (bSuccess == false)
  {
   dwError = Marshal.GetLastWin32Error();
  }
  return bSuccess;
 }

 public  bool SendStringToPrinter(string szPrinterName, string szString)
 {
  IntPtr pBytes;
  Int32 dwCount;
  szString = reemplazarCaracteres(szString);
  // 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;
 }

 private string reemplazarCaracteres(string PrintCommand)
 {
  PrintCommand = PrintCommand.Replace("<STX>", ((char)02).ToString());
  PrintCommand = PrintCommand.Replace("<ETX>", ((char)03).ToString());
  PrintCommand = PrintCommand.Replace("<ESC>", ((char)27).ToString());
  return PrintCommand;
 }
}

'@


Add-Type -TypeDefinition $src -Language CSharpVersion3


$PrinterHelper = new-object RawPrinterHelper



 
Su uso es simple, por ejemplo desde otro archivo ps1 hacemos

. .\PrinterHelper.ps1

$PrinterHelper.SendStringToPrinter('\\PROG03\sato cg408', '<STX><ESC>A1002400880<ESC>A<ESC>H0030<ESC>V0030<ESC>BT101030100<ESC>BW03100*555*<ESC>H0030<ESC>V0133<ESC>WB0555<ESC>Q1<ESC>Z<ETX>') 


Con lo que estaríamos imprimiendo una etiqueta con el valor 555 en code39, imprimiendo el número 555 debajo.
Esta misma clase se puede usar para imprimir desde .Net (con c#)

1 comentario: