?
Solved

sending files to COM

Posted on 2005-04-12
13
Medium Priority
?
345 Views
Last Modified: 2013-11-25
Hi,

I'm interfacing a thermal printer on COM3 via RS232.  From the command prompt, this is all I need:

copy 0.txt COM3: /b

That obviously copies my file to COM3 in binary mode.  Now, how do I do that in .NET?  (I'm new to serial communications and have no idea how to do it in .net)

Thanks - Trevor
0
Comment
Question by:trevorhartman
  • 7
  • 6
13 Comments
 
LVL 10

Accepted Solution

by:
smegghead earned 2000 total points
ID: 13768333
This class prints raw data to a printer. You still have to create a printer on your computer (i think) but point it toward a com or lpt port. The name you pass in is the printer name (in Windows). You may be able to just specify 'com1:' as the printer name, I've not tried it.

Hope it helps..

using System;
using System.Drawing;
using System.Drawing.Printing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;

                              
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)]
      private 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)]
      private 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, 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 = 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;
      }
}
0
 
LVL 8

Author Comment

by:trevorhartman
ID: 13768549
the printer I'm working with is not a standard printer.. it is meant to be used as a sub assembly in kiosks, and it has its own set of commands... to make it print, i send a file in binary mode that contains a "^p" command. will your class still work in this case?

thanks - Trevor
0
 
LVL 10

Expert Comment

by:smegghead
ID: 13770396
yes, you can send anything to the printer. I take it you are talking about control-P ?? you can send any ascii character.
0
NFR key for Veeam Backup for Microsoft Office 365

Veeam is happy to provide a free NFR license (for 1 year, up to 10 users). This license allows for the non‑production use of Veeam Backup for Microsoft Office 365 in your home lab without any feature limitations.

 
LVL 10

Expert Comment

by:smegghead
ID: 13770413
I've used this in the past to print to a receipt printer, which meant that I had to send certain escape sequences to switch fonts, and even to guillotine the paper after printing.

I'm sure this class will work for you.
0
 
LVL 8

Author Comment

by:trevorhartman
ID: 13775735
great, thanks a lot for your help
0
 
LVL 8

Author Comment

by:trevorhartman
ID: 13862605
i got the class working, but it ONLY works if i send files to the printer... the test file i have been sending contains this string:

^P|9|1|405796171|YOUR ESTABLISHMENT|YOUR LOCATION|CITY / STATE / ZIP|TEST COUPON| |405796171|04/12/2005|12:02:21|TICKET# X|FIFTY DOLLARS AND NO CENTS| |$50.00|Expires in 7 days|MACHINE# 0|405796171|^


i need to generate the string dynamically, so rather than create the string, write to file, send file, i want to just send the string directly.   I used:

success = RawPrinterHelper.SendStringToPrinter("\\\\planar\\FL", "^P|9|1|405796171|YOUR ESTABLISHMENT|YOUR LOCATION|CITY / STATE / ZIP|TEST COUPON| |405796171|04/12/2005|12:02:21|TICKET# X|FIFTY DOLLARS AND NO CENTS| |$50.00|Expires in 7 days|MACHINE# 0|405796171|^");

but it doesn't work?  any idea why?

thanks - Trevor
0
 
LVL 10

Expert Comment

by:smegghead
ID: 13862635
maybe you have to pass a form feed ?

What happens if you just send "Hello" ??
0
 
LVL 8

Author Comment

by:trevorhartman
ID: 13862659
doesn't do anything if i just send "Hello"... it has an embedded proprietary printer langauage, and "^p" is the print command, everything after is parameters that populate a ticket template stored in the printer.
0
 
LVL 8

Author Comment

by:trevorhartman
ID: 13862667
note: success returns true every time.. i think the printer is just not intepretting the string that is sent..  everything must be sent binary
0
 
LVL 10

Expert Comment

by:smegghead
ID: 13862723
ok, what if you send ^pHello ??

This works for me sending directly to a printer.
0
 
LVL 8

Author Comment

by:trevorhartman
ID: 13862732
the printer only accepts strings in a very strict format, it requries that all parameters be present.  so "^pHello" doesnt do anything..  


in the SendStringToPrinter, it is converting the string to ANSI text.  do you know how i could convert it into binary instead?  i think that is the problem.
0
 
LVL 10

Expert Comment

by:smegghead
ID: 13862742
As far as I'm aware, ANSI is raw format.

You could always try this article.. it uses the same winspool function, but has an alternative way of calling it.

http://www.codeproject.com/useritems/pclprinting.asp

0
 
LVL 8

Author Comment

by:trevorhartman
ID: 13862760
ok, thanks for the additional help on this one
0

Featured Post

Efficient way to get backups off site to Azure

This user guide provides instructions on how to deploy and configure both a StoneFly Scale Out NAS Enterprise Cloud Drive virtual machine and Veeam Cloud Connect in the Microsoft Azure Cloud.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

More often than not, we developers are confronted with a need: a need to make some kind of magic happen via code. Whether it is for a client, for the boss, or for our own personal projects, the need must be satisfied. Most of the time, the Framework…
A theme is a collection of property settings that allow you to define the look of pages and controls, and then apply the look consistently across pages in an application. Themes can be made up of a set of elements: skins, style sheets, images, and o…
This Micro Tutorial will teach you how to add a cinematic look to any film or video out there. There are very few simple steps that you will follow to do so. This will be demonstrated using Adobe Premiere Pro CS6.
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…

830 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question