none
Printing Directly to Printer

    Question

  • I have a client that has a process which builds a text file. This text file contains commands that is used by their thermal printer, i.e.:

    ^XA^CF,0,0,0^PR12^MD30^PW800%^PON
    ^FO0,147^GB800,4,4^FS
    ^FO0,401^GB800,4,4^FS
    ^FO0,746^GB800,4,4^FS
    ^FO35,12^AdN,0,0^FWN^FH^FDFrom:^FS
    ^FO35,31^AdN,0,0^FWN^FH^FDAri Rothman^FS
    ^FO35,51^AdN,0,0^FWN^FH^

    They want this to print directly to their printer. I have attempted using the following code to produce the results:

    public class Printer
    {
    [DllImport("winspool.Drv", EntryPoint="GetDefaultPrinter")]
    public static extern bool GetDefaultPrinter(
    StringBuilder pszBuffer,
    // printer name buffer
    ref int pcchBuffer // size of name buffer
    );
    [ DllImport( "winspool.drv",CharSet=CharSet.Unicode,ExactSpelling=
    false,
    CallingConvention=CallingConvention.StdCall )]
    public static extern long OpenPrinter(string pPrinterName,
    ref IntPtr phPrinter, int pDefault);
    [ DllImport( "winspool.drv",CharSet=CharSet.Unicode,ExactSpelling=
    false,
    CallingConvention=CallingConvention.StdCall )]
    public static extern long StartDocPrinter(IntPtr hPrinter,
    int Level, ref DOCINFO pDocInfo);
    [ DllImport( "winspool.drv",CharSet=CharSet.Unicode,ExactSpelling=
    true,
    CallingConvention=CallingConvention.StdCall)]
    public static extern long StartPagePrinter(IntPtr hPrinter);
    [ DllImport( "winspool.drv",CharSet=CharSet.Ansi,ExactSpelling=
    true,
    CallingConvention=CallingConvention.StdCall)]
    public static extern long WritePrinter(IntPtr hPrinter,string data,
    int buf,ref int pcWritten);
    [ DllImport( "winspool.drv" ,CharSet=CharSet.Unicode,ExactSpelling=
    true,
    CallingConvention=CallingConvention.StdCall)]
    public static extern long EndPagePrinter(IntPtr hPrinter);
    [ DllImport( "winspool.drv" ,CharSet=CharSet.Unicode,ExactSpelling=
    true,
    CallingConvention=CallingConvention.StdCall)]
    public static extern long EndDocPrinter(IntPtr hPrinter);
    [ DllImport( "winspool.drv",CharSet=CharSet.Unicode,ExactSpelling=
    true,
    CallingConvention=CallingConvention.StdCall )]
    public static extern long ClosePrinter(IntPtr hPrinter);

    public Printer()

    {}

    public static void SendToPrinter(string jobName, string PCL5Commands, string printerName)

    {

    System.IntPtr lhPrinter=new System.IntPtr();

    DOCINFO di = new DOCINFO();

    int pcWritten=0;

    di.pDocName=jobName;

    di.pDataType="RAW";

    OpenPrinter(printerName,ref lhPrinter,0);

    StartDocPrinter(lhPrinter,1,ref di);

    StartPagePrinter(lhPrinter);

    WritePrinter(lhPrinter,PCL5Commands,PCL5Commands.Length,ref pcWritten);

    EndPagePrinter(lhPrinter);

    EndDocPrinter(lhPrinter);

    ClosePrinter(lhPrinter);

    }

    }

     

     

    However, this prints the commands as text. But I am using an HP PCL 6 printer for testing purposes, so it may be caused by the printer not recognizing the commands. I am trying to gain opinions on this situation. Also, is there a more direct way to issue printer commands directly, or is this the best way? I was thinking maybe opening a socket between the client and the printer and feeding this through directly to the port.

     

    Any thoughts?

    Tuesday, 28 March 2006 2:52 PM

Answers

  • I routinely have to do this sort of thing (printing directly to thermal printers). I've used both methods of opening a port and talking directly to the printer or using the printer driver if it had one.

    this is the code I use to go through the driver... it's similar to what you've posted.

    public class PrintThroughDriver

    {

    // Structure and API declarions:

    [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]

    internal 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)]

    internal static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, long pd);

    [DllImport("winspool.Drv", EntryPoint="ClosePrinter", SetLastError=true, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]

    internal static extern bool ClosePrinter(IntPtr hPrinter);

    [DllImport("winspool.Drv", EntryPoint="StartDocPrinterA", SetLastError=true, CharSet=CharSet.Ansi, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]

    internal 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)]

    internal static extern bool EndDocPrinter(IntPtr hPrinter);

    [DllImport("winspool.Drv", EntryPoint="StartPagePrinter", SetLastError=true, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]

    internal static extern bool StartPagePrinter(IntPtr hPrinter);

    [DllImport("winspool.Drv", EntryPoint="EndPagePrinter", SetLastError=true, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]

    internal static extern bool EndPagePrinter(IntPtr hPrinter);

    [DllImport("winspool.Drv", EntryPoint="WritePrinter", SetLastError=true, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]

    internal static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten );

    [DllImport("kernel32.dll", EntryPoint="GetLastError", SetLastError=false, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]

    internal static extern Int32 GetLastError();

    // 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.

    private 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 = "C# Debug Print RAW Document";

    di.pDataType = "RAW";

    // Open the printer.

    if( OpenPrinter( szPrinterName, out hPrinter, 0 ) )

    {

    // 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 = GetLastError();

    }

    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;

    }

     

    }

    internal struct DOCINFO

    {

    [MarshalAs(UnmanagedType.LPWStr)]public string pDocName;

    [MarshalAs(UnmanagedType.LPWStr)]public string pOutputFile;

    [MarshalAs(UnmanagedType.LPWStr)]public string pDataType;

    }

    }

     

    You have make sure that you're sending the proper bytes to the printer. If you're just sending a byte representation of the string of commands you're not actually sending the bytes for the actual commands.

    Tuesday, 28 March 2006 4:08 PM
  • Alternate ways to send printer commands

    Sometimes, as in the case of the LEXMARK “RFID WRITTER” PRINTER, it is useful to have a report output directed to a file first, later you could modify this file as necessary, and then print it at a later time to the printer.

     When this is done, the PCL/POSTSCRIPT printer commands are embedded in the text of the file at the time the report is executed. This file can later be printed directly from Visual FoxPro to either a PCL or PostScript printers.

    This can be done at the time a report is created (in design mode or from the Report Wizard) or after the report is saved (programmatically, or from the Print dialog box). There are only a few steps to print to a file, and the steps are similar under all Windows Operating Systems: Windows 95, Windows NT, Windows XP, and Servers 2000 and 2003 operating systems.

    Step-by-Step Procedure

    1.       Follow your Windows User's guide to install any new printers.

    2.       Once a printer is installed, create a new printer of the same type, and connect it to the File: port instead of a LPT1:, COMx:, or TCP/IP port.

    3.       Set this printer up to be the default printer. (As your default printer, any new reports will be printed directly to a file along with any printer-specific language.) Remember, you can create a report with the Report Wizard or the Report Designer, open the report and save it again. When you save the report to a file, this time the printer driver and printer output device information are stored in the internal structure of the report. You need this information to print it to the right printer. Remember, when a report is saved and the output device is “File:”, the “printer driver” and “printer output device settings” are saved with the report. So, each time a report is printed, the user is prompted for a file name to save and the report is printed to that file.

    4.       Using a HEX editor you can proceed to modify the file, if needed. You will have to have an excellent knowledge and understanding of one or more printer languages like PJL, PCL, Postscript, or other printer languages as the file was written to.

    5.       Print the file, first check that the destination printer is the same as the printer used during the report creation. Then from the Print Setup dialog box, verify that the default printer is now connected to the real printer, not the one pointing to the File: port but to the LPT1: COMx: or TCP/IP port as it should. Next, issue the print command, or click Print on the File menu.

    In the Type list, select “ASCII File”. You receive a warning that the file will be sent directly to the printer and should have all printer-specific language in the file. Enter the file name, and click OK. The file will be sent to the printer and printed exactly the as if the report had been sent directly to the printer.

     

    Friday, 13 April 2007 5:18 PM

All replies

  • I routinely have to do this sort of thing (printing directly to thermal printers). I've used both methods of opening a port and talking directly to the printer or using the printer driver if it had one.

    this is the code I use to go through the driver... it's similar to what you've posted.

    public class PrintThroughDriver

    {

    // Structure and API declarions:

    [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]

    internal 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)]

    internal static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, long pd);

    [DllImport("winspool.Drv", EntryPoint="ClosePrinter", SetLastError=true, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]

    internal static extern bool ClosePrinter(IntPtr hPrinter);

    [DllImport("winspool.Drv", EntryPoint="StartDocPrinterA", SetLastError=true, CharSet=CharSet.Ansi, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]

    internal 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)]

    internal static extern bool EndDocPrinter(IntPtr hPrinter);

    [DllImport("winspool.Drv", EntryPoint="StartPagePrinter", SetLastError=true, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]

    internal static extern bool StartPagePrinter(IntPtr hPrinter);

    [DllImport("winspool.Drv", EntryPoint="EndPagePrinter", SetLastError=true, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]

    internal static extern bool EndPagePrinter(IntPtr hPrinter);

    [DllImport("winspool.Drv", EntryPoint="WritePrinter", SetLastError=true, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]

    internal static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten );

    [DllImport("kernel32.dll", EntryPoint="GetLastError", SetLastError=false, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]

    internal static extern Int32 GetLastError();

    // 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.

    private 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 = "C# Debug Print RAW Document";

    di.pDataType = "RAW";

    // Open the printer.

    if( OpenPrinter( szPrinterName, out hPrinter, 0 ) )

    {

    // 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 = GetLastError();

    }

    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;

    }

     

    }

    internal struct DOCINFO

    {

    [MarshalAs(UnmanagedType.LPWStr)]public string pDocName;

    [MarshalAs(UnmanagedType.LPWStr)]public string pOutputFile;

    [MarshalAs(UnmanagedType.LPWStr)]public string pDataType;

    }

    }

     

    You have make sure that you're sending the proper bytes to the printer. If you're just sending a byte representation of the string of commands you're not actually sending the bytes for the actual commands.

    Tuesday, 28 March 2006 4:08 PM
  • Regarding this statement

    :"You have make sure that you're sending the proper bytes to the printer. If you're just sending a byte representation of the string of commands you're not actually sending the bytes for the actual commands."

    What exactly do you mean? Right now there is a process that builds the FedEx label and stores the data/commands into a text file. My application pulls that text file and I send it into the SendToPrinter method as a string(PCL5Commands).

    It calls the API method WritePrinter(lhPrinter,PCL5Commans,PCL5Commands.Length,ref pcWritten)


    In the method that calls SendToPrinter, I detect and attempt to print to their default printer, which is set as the thermal. It prints to regular laser jets, but the output is illegible. However, the client says it does not print to their thermal printer.

    Also, the thermal printer is connected directly to the printer, as opposed to network. My testing environment uses a networked laser jet.

    Any ideas?

    Monday, 10 April 2006 12:29 PM
  • What I mean is that C# may be converting the string incorrectly before sending it through to the unmanaged API. If you're sending strings to the printer like "^XA^CF,0,0,0^PR12^MD30^PW800%^PON", C# doesn't recognize '^' as an escape character and wouldn't translate and send it as such. The command would then be invalid and the printer would just print it all out as text. I've had this happen many many times. It took me quite some time to get the printer I use printing correctly through printing directly to it.

    We're both using slightly different versions of WritePrinter. The one I'm using is sending bytes so I have to marshall the string of commands to an unmanaged byte array manually. I'm assuming the WritePrinter you're using is doing the marshalling itself and may not be doing it the way you want it to.

    I use commands (for the particular printer I'm using) like:

    public const string esc = "\x1b";
    public const string partial_cut = "\x1f";
    public static string variable_length_page(bool tf) {
      return (esc+"\x63"+(tf?"\x1":"\x0"));
    }

    PrintDirect.SendStringToPrinter("PrinterName", variable_length_page(true));

    I also found this article, which shows sending PCL commands through C#.

    Monday, 10 April 2006 3:06 PM
  • Hi guys,

    I thought I'd throw this option into the mix. I develop point of sale software for restaurants that uses Epson TM thermal printers. For clarity's sake, you're not really printing directly to the printer if you use winspool.drv, you're just bypassing the printer selection dialog form. Whatever you're printing is still being spooled = not printing directly. We use the SDKs OPOS for .Net and Microsoft .Net for POS, which has the benefit of async printing without a spooler and is incredibly fast for thermals.

    Like I said, I just wanted to throw that out there. I realize your problem is probably more syntactical. I'd research the printer codes and make sure your text file codes will, in fact, work. With regards to the non-recognized string escape characters mentioned, you could massage those in your C# code before sending to the printer.

    - nava

    Tuesday, 11 April 2006 8:09 PM
  • Sori am a complete newbie.
    Saturday, 8 July 2006 1:50 AM
  • Can I inject a new wrinkle that I am trying to get through. Printing text is pretty straight forward. How does a person add a image to the file that is being printed, like a concert ticket with a logo on it. I tried writing the bytes to text, but the printer goes right past and continues with the rest of the text.
    Monday, 14 August 2006 8:52 PM
  • Are you using OPOS? If so, adding the image is pretty straight forward.
    Monday, 14 August 2006 8:59 PM
  • hi guys

            plz. consider me new.

        plz. tell me how to print simple two integers , their values or their address tell me how to use default printer.

    plz. send me the whole code....

    thanks

    Tuesday, 15 August 2006 5:38 AM
  • Hi Nava,

    I am a novice programmer devloping a POS application in VS 2003 vb.net. I have some serious trouble printing to a thermal printer that the cusomer is using which has been provided by KUBE (www.Custom.it) thorugh a Serial Port. What function in .net could i use to print directly to the printer. There is some documentation available but only HEX codes are mentioned which I cannot make any sense of. The printer is using the ESC/POS emulation

     

    PLS HELP !!!!!!!!!!!!!!!!!!!

    Shabbir

    Tuesday, 22 August 2006 10:52 AM
  • No, I am trying to write to a datamax with datamax codes. I am trying to save the image in the printer memory and recall it by name.
    Tuesday, 22 August 2006 4:11 PM
  • But, I am open to change. How does opos work?
    Tuesday, 22 August 2006 9:34 PM
  • To send somthing directly to the printer you can try this;

    Create a Process object.
    Command: type  // this is an age-old DOS command to view a file
    Argument: "\"" + FullPathofFile.dat + "\" >  PrinterPort(ex. COM1, LPT1)" // redirect output of 'type' to the PORT

    Thursday, 30 November 2006 8:09 PM
  • Alternate ways to send printer commands

    Sometimes, as in the case of the LEXMARK “RFID WRITTER” PRINTER, it is useful to have a report output directed to a file first, later you could modify this file as necessary, and then print it at a later time to the printer.

     When this is done, the PCL/POSTSCRIPT printer commands are embedded in the text of the file at the time the report is executed. This file can later be printed directly from Visual FoxPro to either a PCL or PostScript printers.

    This can be done at the time a report is created (in design mode or from the Report Wizard) or after the report is saved (programmatically, or from the Print dialog box). There are only a few steps to print to a file, and the steps are similar under all Windows Operating Systems: Windows 95, Windows NT, Windows XP, and Servers 2000 and 2003 operating systems.

    Step-by-Step Procedure

    1.       Follow your Windows User's guide to install any new printers.

    2.       Once a printer is installed, create a new printer of the same type, and connect it to the File: port instead of a LPT1:, COMx:, or TCP/IP port.

    3.       Set this printer up to be the default printer. (As your default printer, any new reports will be printed directly to a file along with any printer-specific language.) Remember, you can create a report with the Report Wizard or the Report Designer, open the report and save it again. When you save the report to a file, this time the printer driver and printer output device information are stored in the internal structure of the report. You need this information to print it to the right printer. Remember, when a report is saved and the output device is “File:”, the “printer driver” and “printer output device settings” are saved with the report. So, each time a report is printed, the user is prompted for a file name to save and the report is printed to that file.

    4.       Using a HEX editor you can proceed to modify the file, if needed. You will have to have an excellent knowledge and understanding of one or more printer languages like PJL, PCL, Postscript, or other printer languages as the file was written to.

    5.       Print the file, first check that the destination printer is the same as the printer used during the report creation. Then from the Print Setup dialog box, verify that the default printer is now connected to the real printer, not the one pointing to the File: port but to the LPT1: COMx: or TCP/IP port as it should. Next, issue the print command, or click Print on the File menu.

    In the Type list, select “ASCII File”. You receive a warning that the file will be sent directly to the printer and should have all printer-specific language in the file. Enter the file name, and click OK. The file will be sent to the printer and printed exactly the as if the report had been sent directly to the printer.

     

    Friday, 13 April 2007 5:18 PM
  • Hi. I am using a EPSON printer.

     

    This is a sample (in old basic).


    PRINT #1, CHR$(&H1B);"@"; 'Initializes the printer (ESC @)
    PRINT #1, CHR$(&H1B);"a";CHR$(1);'Specifies a centered printing position (ESC a)
    PRINT #1, CHR$(&H1B);"!";CHR$(0); 'Specifies font A (ESC !)
    PRINT #1, "January 14, 2002 15:00";
    PRINT #1, CHR$(&H1B);"d";CHR$(3); 'Prints and 3 line feeding (ESC d)
    PRINT #1, CHR$(&H1B);"a";CHR$(0); 'Selects the left print position (ESC a)
    PRINT #1, CHR$(&H1B);"!";CHR$(1); 'Selects font B
    PRINT #1, "TM-U210B $20.00";CHR$(&HA);
    PRINT #1, "TM-U210D $21.00";CHR$(&HA);
    PRINT #1, "PS-170 $17.00";CHR$(&HA);
    PRINT #1, CHR$(&HA); 'Line feeding (LF)

     

    Now i've been trying for weeks (literally) to port this to c#.

     

    I am using the following class named rawPrinterHelper on msdn :

     

    using System;

    using System.Drawing;

    using System.Drawing.Printing;

    using System.Windows.Forms;

    using System.Runtime.InteropServices;

    using System.IO;

     

     

    namespace Impression

    {

    public class DirectHelper

    {

    // 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);

    MessageBox.Show("L'impression est déclenchée maintenant!");

    // 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;

    }

    }

    }

     

     

    ESC d : this seems to be one of the escape sequence i can send to the printer. (I have the manual with all the esc sequence available).

     

    Simple question : Can you provide a sample that would send this sequence to the printer ?

     

    Also is I want to send a linefeed character... How do we proceed ? I've been trying : \n (ascii equivalent to but that just print out to the printer)

     

    Once i understand how to send those I hope i can figure out how to send all the commands.

     

    Thanks in advance for your help.

     

    Best regards.

     

    Mat

     

     

    Wednesday, 6 June 2007 4:42 AM
  • That sounds like a good idea,

     

    But printing to a file does not work in Vista, as detailed in this form: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=874957&SiteID=1

     

    The prompt for the filename does not appear.

     

    Wednesday, 6 June 2007 3:41 PM
  •  

    First you need to: Add reference to Microsoft.PointOfService it is where ever you downloaded the SDK to

    Then:  Imports Microsoft.PointOfService

    Imports System.Runtime.InteropServices

    Imports System.Globalization

    Next: Private m_Printer As Microsoft.PointOfService.PosPrinter = Nothing

    (This goes right under the Inherits System.Windows.Forms.Form)

     

    The Rest of It:

    Private Sub frmThermalPrinter_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    Dim strLogicalName As String

    Dim deviceInfo As DeviceInfo

    Dim posExplorer As PosExplorer

    Dim strCurDir As String

    Dim strFilePath As String

    Dim directIOReturn As DirectIOData

    'Current Directory Path for logos

    strFilePath = "C:\Program Files\TMFLOGO\logos\Logo.bmp"

    strLogicalName = "Thermal" 'You must set to your printer name

    'Create PosExplorer

    posExplorer = New PosExplorer

    m_Printer = Nothing

    Try

    deviceInfo = posExplorer.GetDevice(DeviceType.PosPrinter, strLogicalName)

    m_Printer = posExplorer.CreateInstance(deviceInfo)

    Catch ex As Exception

    ChangeButtonStatus()

    Return

    End Try

    Try

    'Open the device

    m_Printer.Open()

    'Get the exclusive control right for the opened device.

    'Then the device is disable from other application.

    m_Printer.Claim(1000)

    'Enable the device.

    m_Printer.DeviceEnabled = True

    'Output by the high quality mode

    m_Printer.RecLetterQuality = True

    'Release the exclusive control right

    m_Printer.Release()

    Try

    m_Printer.SetBitmap(1, PrinterStation.Receipt, strFilePath, _

    PosPrinter.PrinterBitmapAsIs, PosPrinter.PrinterBitmapCenter)

    Catch ex As PosControlException

    End Try

    Catch ex As PosControlException

    ChangeButtonStatus()

    lblMessage.Text = ex.Message()

    End Try

    End Sub

    Private Sub btnPrint_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPrint.Click

    Dim ESC As String

    Dim dateTime As DateTime = New DateTime

    Dim dateFormat As DateTimeFormatInfo = New DateTimeFormatInfo

    Dim strDate As String

    Dim strbcData As String

    Dim i As Int16

    strbcData = "74"

    i = strbcData.Length

    If i < 6 Then

    If i = 1 Then

    strbcData = "00000" & strbcData

    ElseIf i = 2 Then

    strbcData = "0000" & strbcData

    ElseIf i = 3 Then

    strbcData = "000" & strbcData

    ElseIf i = 4 Then

    strbcData = "00" & strbcData

    ElseIf i = 5 Then

    strbcData = "0" & strbcData

    End If

    End If

    'ESC command

    ESC = Chr(&H1B) 'Your escape command

    'Get Date

    dateTime = System.DateTime.Now()

    dateFormat.MonthDayPattern = "MMMM"

    strDate = dateTime.ToString("MMMM,dd,yyyy, hh:mm", dateFormat)

    Try

    'Print Logo

    m_Printer.PrintNormal(PrinterStation.Receipt, ESC + "|1B")

    'Print address

    m_Printer.PrintNormal(PrinterStation.Receipt, ESC + "|N" _

    + "1234 E Some Road, Phoenix, Arizona" + vbCrLf)

    'Print phone number

    m_Printer.PrintNormal(PrinterStation.Receipt, ESC + "|rA" _

    + "TEL (000)000-0000" + vbCrLf)

    'Print date

    'ESC|cA = Centering char

    m_Printer.PrintNormal(PrinterStation.Receipt, ESC + "|cA" + strDate + vbCrLf + vbCrLf)

    'Print buying goods

    m_Printer.PrintNormal(PrinterStation.Receipt, "apples $20.00" + vbCrLf)

    m_Printer.PrintNormal(PrinterStation.Receipt, "grapes $30.00" + vbCrLf)

    m_Printer.PrintNormal(PrinterStation.Receipt, "bananas $40.00" + vbCrLf)

    m_Printer.PrintNormal(PrinterStation.Receipt, "lemons $50.00" + vbCrLf)

    m_Printer.PrintNormal(PrinterStation.Receipt, "oranges $60.00" + vbCrLf + vbCrLf)

    '//Print th total cost

    '//ESC|bC = Bold

    '//ESC|uC = Underline

    '//ESC|2C = Wide charcter

    m_Printer.PrintNormal(PrinterStation.Receipt, ESC + "|bC" _

    + "Tax excluded. $200.00" + ESC + "|N" + vbCrLf)

    m_Printer.PrintNormal(PrinterStation.Receipt, ESC + "|uC" _

    + "Tax 5.0% $10.00" + ESC + "|N" + vbCrLf)

    m_Printer.PrintNormal(PrinterStation.Receipt, ESC + "|bC" + ESC + "|2C" _

    + "Total $210.00" + ESC + "|N" + vbCrLf)

    m_Printer.PrintNormal(PrinterStation.Receipt, "Customer's payment $250.00" + vbCrLf)

    m_Printer.PrintNormal(PrinterStation.Receipt, "Change $40.00" + vbCrLf + vbCrLf)

    '<<<step4>>--Start

    If m_Printer.CapRecBarCode = True Then

    'Bacode printing

    m_Printer.PrintBarCode(PrinterStation.Receipt, strbcData, _

    BarCodeSymbology.Itf, 90, _

    m_Printer.RecLineWidth, PosPrinter.PrinterBarCodeCenter, _

    BarCodeTextPosition.Below)

    End If

    'Feed the receipt to the cutter position automatically, and cut.

    'ESC|#fP = Line Feed and Paper cut

    m_Printer.PrintNormal(PrinterStation.Receipt, ESC + "|#fP")

    Catch ex As PosControlException

    Dim sError As String = ex.Message()

    Finally

    m_Printer.Release()

    m_Printer.Close()

    End Try

    End Sub

    Private Sub ChangeButtonStatus()

    'Disable control.

    btnPrint.Enabled = False

    End Sub

    Monday, 10 September 2007 9:05 PM
  • "First you need to: Add reference to Microsoft.PointOfService it is where ever you downloaded the SDK to"

     

    Which SDK is this?  Also,

     

    "Next: Private m_Printer As Microsoft.PointOfService.PosPrinter = Nothing"

     

    I downloaded and installed MS POS .NET 1.11, and the PosPrinter option is not there.

     

    Actually, OPOS may not be what I need anyway.  I was referred here by another forum.  I am trying to print ID cards with mag stripes, which entails sending code characters the printer recognizes as "sentinels" which tell the printer to encode the text enclosed between the "sentinels" to the mag stripe.  This works when the text is printed from any text editor (Notepad, ConText, whatever) but not from the PrintDocument object, and not from Crystal Reports.

    Tuesday, 9 October 2007 3:24 PM
  • I testes this code, that is included with some examples that epson provides, and they all work fine, but there's one problem.
    How can i select the printer using it's name or other thing instead of the logical name that has to be setted with some tool?
    Code below


    deviceInfo = posExplorer.GetDevice(DeviceType.PosPrinter, strLogicalName)

    m_Printer = posExplorer.CreateInstance(deviceInfo)

    Tuesday, 23 October 2007 10:57 PM
  • When printing directly to the printer does anyone know if theres a good way to know when the printing is complete?  I'm writing code for POS printers and we'll have support for OPOS printers, but we're also going to have support for non-OPOS compliant printers by setting up the appropriate escape sequences.  I would like to have feedback when the printing is done so that we can show the user an accurate representation of what has been printed, what is printing and what will be printed as a typical transaction will send multiple items to the printer.  For non-OPOS compliant printers I'm using the code posted at http://support.microsoft.com/?kbid=322091 to print directly to the printer, but so far I've had no luck figuring out how to determine what has been printed.

     

    Thanks

    Wednesday, 24 October 2007 7:42 PM
  • the following sequences are ESC/POS and they can be used with the RawPrinterHelper class that was exposed previously by Mgrondin345 in this Forum.

     

    private String OpenCashDrawer() {

    StringBuilder sequence = new StringBuilder();

    sequence.Append((char)27);

    sequence.Append((char)112);

    sequence.Append((char)0);

    sequence.Append((char)25);

    sequence.Append((char)250);

     

    return sequence.ToString();

    }

     

    private String InitializePrinter()

    {

    StringBuilder sequence = new StringBuilder();

    sequence.Append((char)27);

    sequence.Append((char)64);

     

    return sequence.ToString();

    }

    private String PrintCenterText()

    {

    //The printer will continue printing at center

    StringBuilder sequence= new StringBuilder();

    sequence.Append((char)27);

    sequence.Append((char)97);

    sequence.Append((char)1);

     

    return sequence.ToString();

    }

    private String PrintLeftText()

    {

    //The printer will continue printing at left

    StringBuilder sequence= new StringBuilder();

    sequence.Append((char)27);

    sequence.Append((char)97);

    sequence.Append((char)0);

     

    return sequence.ToString();

    }

    private String CutPaper()

    {

    StringBuilder sequence = new StringBuilder();

    sequence.Append((char)27);

    sequence.Append((char)105);

    sequence.Append((char)0);

    sequence.Append((char)25);

     

    return sequence.ToString();

    }

     

    private String FeedPaper(int pNumLines)

    {

    StringBuilder sequence= new StringBuilder();

    sequence.Append((char)27);

    sequence.Append((char)100);

    sequence.Append((char)pNumLines);

     

    return sequence.ToString();

    }

    ---------------------------------------------------------------------------------------------

    this is a code example for use the previous functions with the RawPrinterHelper class:

     

    StringBuilder TextToPrinter = new StringBuilder();

    TextToPrinter.Append(InitializePrinter() + OpenCashDrawer() + "an example of text" + FeedPaper(10) + CutPaper());

    RawPrinterHelper.SendStringToPrinter(Printer, TextToPrinter.ToString());

     

    ----------------------------------------------------------------------------------------------

    I hope this Help you. bye

    Saturday, 17 November 2007 11:44 PM
  • Great, it was just what i was looking for.

    First it didn't work but i set

       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.pOutputFile = null;
                di.pDataType = "RAW;
       .....
    }

    and it went perfect!

    thanx
    Monday, 19 November 2007 10:22 AM
  • You`re Welcome.

     

    Wednesday, 21 November 2007 2:40 AM
  • I need to resize the font size in  printing raw data with VB.NET.

    Please anybody have an example of source code?

    Before this, I used VB 6 to print raw data with code like this :

     

         Open "LPT1" For Output As #1
                Print #1, Chr$(&H1B); "@";
                Print #1, Chr$(&H1B); "a"; Chr$(0);
                Print #1, Chr$(&H1B); "!"; Chr$(0); vbCrLf;
                Print #1, "PT INDAH KIAT PULP & PAPER Tbk."; vbCrLf;
                Print #1, "PERAWANG MILL"; vbCrLf; vbCrLf;
                Print #1, Chr$(&H1B); "a"; Chr$(1);
                Print #1, Chr$(&H1B); "!"; Chr$(8);
                Print #1, "VEHICLE PASS"; vbCrLf; vbCrLf; vbCrLf;
                Print #1, Chr$(&H1B); "a"; Chr$(0);
                Print #1, Chr$(&H1B); "!"; Chr$(0);
                Print #1, "Pass No." & vbTab; ": ";
                Print #1, Chr$(&H1B); "!"; Chr$(8);
                Print #1, Chr$(&H1B); "W1"; Chr$(0);
                Print #1, SrNo; vbCrLf;
                Print #1, Chr$(&H1B); "!"; Chr$(0) & vbCrLf;
                Print #1, "Vehicle    "; vbTab; ": " & rs("VehID") & " - " & rs("VehType"); vbCrLf;
                Print #1, "Driver     "; vbTab; ": " & rs("Driver"); vbCrLf;
                Print #1, "Remark     "; vbTab; ": " & rs("CI_Remark"); vbCrLf; vbCrLf;

          Close #1

     

    And now, I want to migrate it to VB.NET.

    I have try using rawprinterhelper class and its worked.

    But, I want to change the font size.

     

    Any one can help me?

    Please

     

    Thanks before

     


         

    Saturday, 8 December 2007 6:25 AM
  • I am currently using this RawPrinterHelper.cs to print directly to my EPSON printer.

     

    Everything works fine, except it doesnt print greek, which is not good, but the other problem is that it takes about 4 or 5 seconds for the print job to leace the Printer Queue.

     

    So when I just send an open Cash drawer command the command gets executed but if I send another command quickly after the first it gets stuck behind the first one. And when I look at the Printer Queue I see the first document is still in there doing nothing.

     

    Does anybody else have this problem or know how to fix it.

     

    I am just using the original RawPrinterHelper.

     

    Thursday, 20 December 2007 4:09 PM
  • i use you r code But it thrown an error to me ...


    Note Error :

    Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

    Method Name :
    ---------------------
    systemshutdown.DirectHelper.SendBytesToPrinter("Star TSP613 Raster Printer", IntPtr.Zero, 1);

    Line :
    --------------
    bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
    RaamkumarDhandapani
    Friday, 12 June 2009 1:31 PM
  • I have tried your code It's working fine... but some unformated datas are printed in paper. i need to print My content how to do that format data..

    kindly Help Me....


    Thanks in Advance

    RaamkumarDhandapani
    Friday, 12 June 2009 2:34 PM
  • I am working on a POS application in which i have to send print on an Epson printer.

    Our client says that he do not want to use drivers for printers or any other third party tool.

    I did same like you.

    But method SendBytesToPrinter(szPrinterName, pBytes, dwCount); takes printer name

    My question is how to get name of printer if its drivers are not installed.

    can i pass the port name to which printer is installed instead of printer name.

     

    thanks in advane.

    Wednesday, 1 December 2010 9:30 AM
  • The "SendBytesToPrinter" methodology, I believe, requires a driver even if it is the Microsoft Generic Epson driver. You will need the port enumeration Win32 API instead, and send the data to the port.

    Thursday, 16 December 2010 12:06 AM
  • thanks for your reply.

    I resolved it  using system.Io.ports namepace in .net.

    i used serialport class and use it to send data directly to port in bytes. where printer is attached .I used Epson control commands.if any body needs sample i can post it.

    Wednesday, 22 December 2010 6:07 AM
  • I am facing an issue with the thermal printer and it won't work properly. After every print, font goes smaller.

    I am using EPSON T220 printer.

    I am calling simply window.print() when hitting on print button.

    Kindly advise will be grateful to you

     

    Wednesday, 6 April 2011 12:24 PM
  • thanks for your reply.

    I resolved it  using system.Io.ports namepace in .net.

    i used serialport class and use it to send data directly to port in bytes. where printer is attached .I used Epson control commands.if any body needs sample i can post it.

    I have an application where it required to print text file to network printer. In vb6 i used shellexecute which worked fine.

    In vb.net i am using a batch file to issue the print command to lpt / network printer (using its share name \\machine\printername) and calling the batchfile with process.start("batchfile with fullpath")

    But It does not print to the printer, is this a security issue with XP clients.

    I thought ur solution might help me out..

    can u post the sample code

    thanks in advance.

     

    Wednesday, 25 May 2011 5:56 PM
  • Hi Zain,

    Please upload/send your code. I think I have a small freelance assignment for you. please mail me your contact details at saurabh[at]realbox.in

    - Saurabh

    Tuesday, 19 July 2011 6:30 AM
  • Hi keith,

    Me also looking for the same, which fedex thermal label printer directly print to the thermal printer and in client location, not for server system as i'm developing web application, if possible please provide me the solution in detail, my id prasad.maganti@live.com

    Sunday, 30 October 2011 4:02 PM
  • Hi Zain,

    Please provide me the solution where i want to print a label to the thermal label printer directly in the client location as i'm developing web application.It's urgent, thanks for help in advance...

    Sunday, 30 October 2011 4:04 PM
  • It's  not work on Windows 8.1 !!!!
    Thursday, 30 January 2014 7:14 AM