SerialPort, USB ports and Port Names

S

sklett

I'm trying to send some printer commands (ZPLII) to an attached USB printer
using the SerialPort component. I didn't get very far at all. In fact I
haven't gotten anywhere.

The first problem I encountered is that a call to SerialPort.GetPortNames()
returns an empty string[]. In other words, NO port names are returned. I'm
not terribly knowledgable about ports but from the Hardware Manager I did
notice that I don't have the Ports and Devices entry (I think that's what
it's called).

If I show the properties dialog for an installed printer and change to the
Ports tab I see several ports listed (LPT1, COM1, USB001, etc).

So my question is: Should SerialPort.GetPortNames() be returning the USB,
LPT1 and COM ports I see in the printer dialog? Am I expecting it to do
somethinh it shouldn't?

There very simple line of code:
string[] ports = System.IO.Ports.SerialPort.GetPortNames();

The port I want to open is called "USB001" - when I try to open that port
using the SerialPort component I get an exception that states the name must
start with "COM".
So my #2 question is: What is the method that you all use to communicate
with a USB attached device? If it's not the SerialPort component, is there
another component in the class library?

I thought this would be a piece of cake!

Thanks for any help,
Steve
 
I

Ignacio Machin ( .NET/ C# MVP )

I'm trying to send some printer commands (ZPLII) to an attached USB printer
using the SerialPort component.  I didn't get very far at all.  In fact I
haven't gotten anywhere.

The first problem I encountered is that a call to SerialPort.GetPortNames()
returns an empty string[].  In other words, NO port names are returned.  I'm
not terribly knowledgable about ports but from the Hardware Manager I did
notice that I don't have the Ports and Devices entry (I think that's what
it's called).

If I show the properties dialog for an installed printer and change to the
Ports tab I see several ports listed (LPT1, COM1, USB001, etc).

So my question is:  Should SerialPort.GetPortNames() be returning the USB,
LPT1 and COM ports I see in the printer dialog?  Am I expecting it to do
somethinh it shouldn't?

There very simple line of code:
string[] ports = System.IO.Ports.SerialPort.GetPortNames();

The port I want to open is called "USB001" - when I try to open that port
using the SerialPort component I get an exception that states the name must
start with "COM".
So my #2 question is:  What is the method that you all use to communicate
with a USB attached device?  If it's not the SerialPort component, is there
another component in the class library?

I thought this would be a piece of cake!

Thanks for any help,
Steve

Hi,

Apparentely your problem is that you aer tryig to use the serial port
and the printer is connected to USB.
Can you connect your printer using serial cable?
Is this a Zebra printer?
 
B

Ben Voigt [C++ MVP]

sklett said:
I'm trying to send some printer commands (ZPLII) to an attached USB
printer using the SerialPort component. I didn't get very far at
all. In fact I haven't gotten anywhere.

Your USB printer implements the printer device class, not the communications
device class. SerialPort can only be used with communications port drivers,
which are automatically loaded for standard UART chips, CDC USB devices, and
are also provided for some USB/serial converter chips that aren't CDC. Your
printer doesn't fall in that category.

OTOH, the Win32 printing API lets you send various device-specific commands
using Escape, ExtEscape, and/or WritePrinter. I don't know whether .NET
provides these or you have to p/invoke them.
 
S

Steve K

Ignacio said:
Hi,

Apparentely your problem is that you aer tryig to use the serial port
and the printer is connected to USB.
Can you connect your printer using serial cable?
Is this a Zebra printer?

Hi Ignacio,

Than you for the reply!

You are correct, the printer is connected to the USB. I had it in my
head that although it was using a USB port, this was somehow "really a
COM port" behind the scenes. I know nothing about ports, USB, etc.

I can connect the printer via serial but would consider it a last
resort. We have 8 of these printers deployed around our office and
warehouse, the cable needed to connect via serial requires drivers to be
installed, etc. Actually, the more I think about this... no, I don't
think I can make a true serial connection - the cable I refer to is a
Serial -> USB converter or it may even be a Parallel -> USB (it has the
2.5" wide connector on one end and USB on the other.

I'm pretty sure my problem is 100% due to a lack of understanding of how
ports work and the different kinds of ports.


For example, we use a web based ERP/CRM application called "NetSuite" -
In the NetSuite help they have a section on "Thermal Printing"
The instructions say to create a *.bat file with the text:
"copy %1 LPT1"
then to associate the file extension EPL2 with this bat file.

To me this means that when NetSuite serves up an EPL2 file and the
browser Open/Save dialog is presented I will choose "Open" which in turn
will pass the file to the bat file which in turn will copy the printer
commands contained to the LPT1 port.

So in a way, I think I just answered part of my question ;0)
(I just found this help section in NetSuite before responding to your post)

What I'm looking to do is find a way to "write" to the printer from my
C# application. The postage web service that I'm preparing to use can
return the postage in several formats falling into two categories: image
or printer commands. The printer commands are much smaller and print
faster so they were my first choice.

Oh, to answer your question: Yes, these are Zebra printers, we have
both 3844-Z and 2844 (cheapos).

Hopefully this additional information will give you a better idea of
what I'm after.

Thanks again for the reply!
-Steve
 
S

Steve K

Ben said:
Your USB printer implements the printer device class, not the communications
device class. SerialPort can only be used with communications port drivers,
which are automatically loaded for standard UART chips, CDC USB devices, and
are also provided for some USB/serial converter chips that aren't CDC. Your
printer doesn't fall in that category.
Wow, you know your stuff. I recognize UART from when I had to make some
emergency firmware changes to our product's firmware, but most of the
other things you mention are over my head ;0)
OTOH, the Win32 printing API lets you send various device-specific commands
using Escape, ExtEscape, and/or WritePrinter. I don't know whether .NET
provides these or you have to p/invoke them.

WritePrinter sounds promising, I will look into this. As I mentioned in
another post, I think what I'm after is to perform the equivalent of:
copy <filename> LPT1

Where the above is typed in a command prompt. If this means I use Win32
stuff (maybe WritePrinter?) then so be it.

I threw together some quick code to print an image rather than try to
send the printer commands to get my proof of concept done for a meeting,
but I would still like to get the printer command solution working and
it would be nice to learn something new as well.

Thanks for the reply,
Steve
 
S

Steve K

Peter said:
Why do you want to do this? What's in "<filename>"? Are you really
sending some sort of specific printer commands? Or are you trying to
replicate the old DOS-style "print a text file" functionality? In your
original post, you said you want to send printer commands, but copying a
file to the parallel port isn't a common way to do that.

filename contains "ZPLII" (Zebra Printing Language 2) commands.
Apparently, from what I've read you can either copy a file containing
these commands or write the commands, one line at a time directly to the
printer.

My motivation for sending the commands versus using the .Net printing
(which I'm doing for every other print need in my application) is that
the base64 encoded PNG images from the web service supplying the postage
data is much larger than the printer command data. To clarify; I can
request postage as a bitmap OR as printer commands. The printer
commands option results in quicker turnaround from the service call as
well as the printer starting to print faster.

Another possible option would be to develop a ZPLII parser/renderer but
I highly doubt that would pay off in any way! ;0) (except knowledge gained)
If the latter, IMHO you might as well just do it the "official" way: use
the .NET printing API to print your text file. It's not really all that
complicated and it will be much more general purpose, portable, and
flexible.

This is my backup plan and the more I'm googling about working with a
USB connected printer the more I'm leaning to this option. There is a
definite point when performance is far out shadowed by nasty hacks and
bloated code.
If the former, there's a small possibility that whatever you're
ultimately trying to achieve is dealt with better through some other
means. If you can give a higher-level description of your goal, maybe
there'd be better advice.

See first comment for high level description.
If you are stuck on sending explicit data to the printer, I'd agree with
Ben that the Win32 direct-to-printer functions are about all you've
got. AFAIK there's nothing in .NET that would allow that, and this KB
article seems to verify that: http://support.microsoft.com/kb/322091
(the article also includes some sample code for sending data in C# using
WritePrinter() via p/invoke).

This is my next avenue to check out. If I can't make some progress in
the next 4 hours I will abandon the printer command option and opt for
the bitmap/GDI option.

Thanks for the reply,
Steve
 
P

Peter Morris

I print on an RW 420 and that comes with an interop library.


private static ZebraPrintCtlClass ZebraPrinter;
public void Print(int portNumber, int baudRate, string printData)
{
try
{
ZebraPrinter.SerialConnection(string.Format("COM{0}:", portNumber),
baudRate);
ZebraPrinter.Open();
ZebraPrinter.Print(printData);
}
finally
{
ZebraPrinter.Close();
}
}


Is that how you are printing?


Pete
 
C

Charlie

I figured out what was going wrong. Well, at least I think I did.

After re-reading the programmer's manual from front to back, I came across a
reference to the fact that the CR/LF's are important and that if the 1st line
of printer code is not correct, the printer then interprets the code as text
and acts as a legacy text-only line printer.

So, I tried using the CPCL code (which the manual said is the preferred
method for new applications) and something like this:

SerialPort sp = new SerialPort("COM4", 19200);

string l1 = "! 0 200 200 210 1";
string l2 = "TEXT 4 0 30 40 Hello World";
string l3 = "FORM";
string l4 = "PRINT";

sp.Open();
sp.WriteLine(l1);
sp.WriteLine(l2);
sp.WriteLine(l3);
sp.WriteLine(l4);
sp.Close();

THis worked fine for me so I'm assuming there were no hard line breaks in
the ZPL code I was using which caused it to error out.

Thanks for your help.

Charlie
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top