Discussion:
How to create a printer port?
(too old to reply)
Terry Olsen
2007-02-07 05:57:01 UTC
Permalink
Does anyone have any code on creating a printer port that prints to a
specific file?
Dave O.
2007-02-07 11:21:34 UTC
Permalink
There is already a printer driver supplied with windows called "Generic /
Text Only" which can be set to print to file (though not as far as I know by
default). If you do use this driver NEVER make it the default driver as you
will lose most of your fonts while it is the default driver - Windows only
shows type faces that are supported by the default printer, if the default
printer supports no typefaces then that is what you get!
I think you'll find that writing printer drivers is not generally a task for
VB.

Best Regards
Dave O.
Post by Terry Olsen
Does anyone have any code on creating a printer port that prints to a
specific file?
Terry Olsen
2007-02-07 13:53:42 UTC
Permalink
I don't want to create a driver. I want to use the AddPort & AddMonitor API
functions to create a printer port that writes to a file. But I can find no
code examples on how to do this.
Post by Dave O.
There is already a printer driver supplied with windows called "Generic /
Text Only" which can be set to print to file (though not as far as I know
by default). If you do use this driver NEVER make it the default driver as
you will lose most of your fonts while it is the default driver - Windows
only shows type faces that are supported by the default printer, if the
default printer supports no typefaces then that is what you get!
I think you'll find that writing printer drivers is not generally a task
for VB.
Best Regards
Dave O.
Post by Terry Olsen
Does anyone have any code on creating a printer port that prints to a
specific file?
Dave O.
2007-02-07 13:58:40 UTC
Permalink
I want to use the AddPort & AddMonitor API functions to create a printer
port that writes to a file. But I can find no code examples on how to do
this.
OK, let's take this from the top, what are you actually trying to do? If you
just want to write to a file there are a zillion ways to do that all of
which are easier than writing through a print to file printer port.

Regards
Dave O.
Michael R Mattys
2007-02-07 14:31:26 UTC
Permalink
Post by Dave O.
I want to use the AddPort & AddMonitor API functions to create a printer
port that writes to a file. But I can find no code examples on how to do
this.
OK, let's take this from the top, what are you actually trying to do? If
you just want to write to a file there are a zillion ways to do that all
of which are easier than writing through a print to file printer port.
Regards
Dave O.
How 'bout an image of a street-map? :)
--
Michael R. Mattys
MapPoint & Access Dev
www.mattysconsulting.com
Rick Rothstein (MVP - VB)
2007-02-07 15:09:05 UTC
Permalink
Post by Michael R Mattys
Post by Dave O.
I want to use the AddPort & AddMonitor API functions to create a printer
port that writes to a file. But I can find no code examples on how to do
this.
OK, let's take this from the top, what are you actually trying to do? If
you just want to write to a file there are a zillion ways to do that all
of which are easier than writing through a print to file printer port.
How 'bout an image of a street-map? :)
But simply printing an image (of anything) to a file will probably not
produce a usable file in the end. The whole idea of printers in Windows is
that how an individual printer interprets the printing process is hidden
from the user (via the printer driver); each printer is different (in the
old days, before Windows, using printers was a nightmare... you had to
install a printer that the individual program recognized and you had to do
that for each program) and the data printed to a file needs to know the type
of printer that will eventually be used to physically print the data out.
Windows already provides a mechanism to do that via its Add Printer wizard.
Using it, you can create a "Print To File" printer, but you have to
associate it with a specific printer (or the Generic Text printer) in order
for Windows to know how to write the data to the file. That data will then
only be usable by the printer the Print To File is associated with (sort of
a method to delay printing data until a later time and giving you a method
to save what you print). I think (and so does Dave) that the OP may have
something different in mind than this which he believes printing to file may
solve, but I (we) think there is more to the story than that, hence Dave's
question.

Rick
Dave O.
2007-02-07 15:13:38 UTC
Permalink
Post by Michael R Mattys
Post by Dave O.
I want to use the AddPort & AddMonitor API functions to create a printer
port that writes to a file. But I can find no code examples on how to do
this.
OK, let's take this from the top, what are you actually trying to do? If
you just want to write to a file there are a zillion ways to do that all
of which are easier than writing through a print to file printer port.
Regards
Dave O.
How 'bout an image of a street-map? :)
--
Michael R. Mattys
MapPoint & Access Dev
www.mattysconsulting.com
Just save it as a Bitmap or JP(E)G. The only way to get anything useful on
graphics via a printer is as postscript data, anything else will be in
printer specific encoding which is in most cases as much use as random data.
Using AddPort & AddMonitor just seems a way of adding unnecessary
complication.

Regards
Dave O.
Terry Olsen
2007-02-08 00:39:40 UTC
Permalink
I have a program that prints labels to a thermal label printer. I need to
intercept the label data before it gets to the printer and modify it with my
program. My program will be distributed to end users, so I need to make it
as seamless as possible for them. I don't want them to have to go manually
create and change printers.

My program will insert itself between the label printing program and the
printer. So I need to programmatically create a "Temporary Printer" that
prints to the label printer. I also need to programmatically change the
"Original Label Printer" to print to a file.

This way, when the label printing program prints a label to the "Original
Label Printer", the data will get written to a file. My program will see the
file get created, modify the data, and then send it out to the "Temporary
Printer" to actually print the modified label.

When my program gets closed, it will restore the "Original Label Printer" to
print directly to the label printer, and remove the "Temporary Printer".

This is not an original idea. I'm trying to duplicate a program that already
does this but the source code has been lost.

I have been able to create the "Temporary Printer" using the AddPrinter API
call, but I don't know how to create a "Print to file" port so that I can
redirect the "Original Label Printer" to it. When the old program is
started, it creates a port called: "C:\temp\label.out" and redirects the
"Original Label Printer" to that port.

I hope I have explained myself clearly enough for you to get the idea of
what i'm doing. Any help is appreciated.
Post by Dave O.
I want to use the AddPort & AddMonitor API functions to create a printer
port that writes to a file. But I can find no code examples on how to do
this.
OK, let's take this from the top, what are you actually trying to do? If
you just want to write to a file there are a zillion ways to do that all
of which are easier than writing through a print to file printer port.
Regards
Dave O.
Dave O.
2007-02-08 09:39:50 UTC
Permalink
So you want to print to a file. A test first, if using the existing printer
driver (or the Generic/Text one) you select the "Print to File" option is
the file created adequate for your needs?
Because if it is, the solution of creating printer ports does seem a bit
excessive, all you need to do is get that file, process it and then print
it. I say "all", it is not exactly trivial but I'm sure it can be done.

Regards
Dave O.
Post by Terry Olsen
I have a program that prints labels to a thermal label printer. I need to
intercept the label data before it gets to the printer and modify it with
my program. My program will be distributed to end users, so I need to make
it as seamless as possible for them. I don't want them to have to go
manually create and change printers.
My program will insert itself between the label printing program and the
printer. So I need to programmatically create a "Temporary Printer" that
prints to the label printer. I also need to programmatically change the
"Original Label Printer" to print to a file.
This way, when the label printing program prints a label to the "Original
Label Printer", the data will get written to a file. My program will see
the file get created, modify the data, and then send it out to the
"Temporary Printer" to actually print the modified label.
When my program gets closed, it will restore the "Original Label Printer"
to print directly to the label printer, and remove the "Temporary
Printer".
This is not an original idea. I'm trying to duplicate a program that
already does this but the source code has been lost.
I have been able to create the "Temporary Printer" using the AddPrinter
API call, but I don't know how to create a "Print to file" port so that I
can redirect the "Original Label Printer" to it. When the old program is
started, it creates a port called: "C:\temp\label.out" and redirects the
"Original Label Printer" to that port.
I hope I have explained myself clearly enough for you to get the idea of
what i'm doing. Any help is appreciated.
Post by Dave O.
I want to use the AddPort & AddMonitor API functions to create a printer
port that writes to a file. But I can find no code examples on how to do
this.
OK, let's take this from the top, what are you actually trying to do? If
you just want to write to a file there are a zillion ways to do that all
of which are easier than writing through a print to file printer port.
Regards
Dave O.
Terry Olsen
2007-02-08 14:17:53 UTC
Permalink
Well, if creating a printer port that points to a file is "a bit excessive",
how do I go about intercepting the label data _before_ it's printed, so I
can modify it and then send it out to the printer? I'm not asking how to
edit the label data. I already know how to do that.
Post by Dave O.
So you want to print to a file. A test first, if using the existing
printer driver (or the Generic/Text one) you select the "Print to File"
option is the file created adequate for your needs?
Because if it is, the solution of creating printer ports does seem a bit
excessive, all you need to do is get that file, process it and then print
it. I say "all", it is not exactly trivial but I'm sure it can be done.
Regards
Dave O.
Post by Terry Olsen
I have a program that prints labels to a thermal label printer. I need to
intercept the label data before it gets to the printer and modify it with
my program. My program will be distributed to end users, so I need to make
it as seamless as possible for them. I don't want them to have to go
manually create and change printers.
My program will insert itself between the label printing program and the
printer. So I need to programmatically create a "Temporary Printer" that
prints to the label printer. I also need to programmatically change the
"Original Label Printer" to print to a file.
This way, when the label printing program prints a label to the "Original
Label Printer", the data will get written to a file. My program will see
the file get created, modify the data, and then send it out to the
"Temporary Printer" to actually print the modified label.
When my program gets closed, it will restore the "Original Label Printer"
to print directly to the label printer, and remove the "Temporary
Printer".
This is not an original idea. I'm trying to duplicate a program that
already does this but the source code has been lost.
I have been able to create the "Temporary Printer" using the AddPrinter
API call, but I don't know how to create a "Print to file" port so that I
can redirect the "Original Label Printer" to it. When the old program is
started, it creates a port called: "C:\temp\label.out" and redirects the
"Original Label Printer" to that port.
I hope I have explained myself clearly enough for you to get the idea of
what i'm doing. Any help is appreciated.
Post by Dave O.
I want to use the AddPort & AddMonitor API functions to create a printer
port that writes to a file. But I can find no code examples on how to do
this.
OK, let's take this from the top, what are you actually trying to do? If
you just want to write to a file there are a zillion ways to do that all
of which are easier than writing through a print to file printer port.
Regards
Dave O.
Dave O.
2007-02-08 16:11:18 UTC
Permalink
Post by Terry Olsen
how do I go about intercepting the label data _before_ it's printed,
You don't, you print to file (or perhaps to stdout, no idea how but must be
possible) then process the data then print as usual.
The fun stars when you want all that to be automatic.

Regards

Dave O.
Post by Terry Olsen
Post by Dave O.
So you want to print to a file. A test first, if using the existing
printer driver (or the Generic/Text one) you select the "Print to File"
option is the file created adequate for your needs?
Because if it is, the solution of creating printer ports does seem a bit
excessive, all you need to do is get that file, process it and then print
it. I say "all", it is not exactly trivial but I'm sure it can be done.
Terry Olsen
2007-02-09 01:27:22 UTC
Permalink
Exactly! Which is why I asked how to create a "Print To File" port
programmatically in the first place.
Post by Dave O.
Post by Terry Olsen
how do I go about intercepting the label data _before_ it's printed,
You don't, you print to file (or perhaps to stdout, no idea how but must
be possible) then process the data then print as usual.
The fun stars when you want all that to be automatic.
Regards
Dave O.
Post by Terry Olsen
Post by Dave O.
So you want to print to a file. A test first, if using the existing
printer driver (or the Generic/Text one) you select the "Print to File"
option is the file created adequate for your needs?
Because if it is, the solution of creating printer ports does seem a bit
excessive, all you need to do is get that file, process it and then
print it. I say "all", it is not exactly trivial but I'm sure it can be
done.
Dave O.
2007-02-09 11:13:36 UTC
Permalink
Which takes back to the start, as you cannot modify the originating program
you have to deal with the output which means getting at the print data,
which in turn means setting up a print DRIVER which prints to the "Print to
File" port.

This gives you 2 options,
1) Write a new driver which only prints to file - I suspect not possible
with VB, hopefully some one can prove me wrong on that but I wouldn't hold
my breath.
2) Force an existing printer driver to output to file and to a specific file
without popping up the "Output File Name" dialog which the existing "Print
to File" driver currently does. Again I don't know if there is a way to do
this directly, but there is a way to spoof it:

To make the whole operation seamless write a launcher to run the existing
labeller program whose driver you've set to "Print to File", then the
launcher monitors what window is topmost, when the "Output File Name" dialog
pops up it uses SendMessage to fill in the file name and press the OK
button, this will happen in "the blink of an eye". The program also monitors
the folder where the file is to be written and as soon as the file is
available it can do whatever is needed then send the file to the printer.
This program should also monitor what programs are running so when the
labeller program is closed the launcher unloads itself.

That may seem complicated but each part is possible so bringing the lot
together should not be too hard, certainly easier than writing a new printer
driver.

Best wishes
Dave O.
Post by Terry Olsen
Exactly! Which is why I asked how to create a "Print To File" port
programmatically in the first place.
Post by Dave O.
Post by Terry Olsen
how do I go about intercepting the label data _before_ it's printed,
You don't, you print to file (or perhaps to stdout, no idea how but must
be possible) then process the data then print as usual.
The fun stars when you want all that to be automatic.
Regards
Dave O.
Post by Terry Olsen
Post by Dave O.
So you want to print to a file. A test first, if using the existing
printer driver (or the Generic/Text one) you select the "Print to File"
option is the file created adequate for your needs?
Because if it is, the solution of creating printer ports does seem a
bit excessive, all you need to do is get that file, process it and then
print it. I say "all", it is not exactly trivial but I'm sure it can be
done.
Terry Olsen
2007-02-23 04:14:29 UTC
Permalink
Not to beat a dead horse, but I still haven't figured out how to do this
with the API. I did figure out how to do it using the PRNADMIN.DLL COM
Library like so:

Public Sub CreateFilePort(ByVal FilePath As String)
Dim PRNADMIN As New PRNADMINLib.PrintMaster
Dim port As New PRNADMINLib.Port
port.PortName = FilePath
port.PortType = 3 'Standard Local Port
PRNADMIN.PortAdd(port)
End Sub

This adds a printer port that directs printer data to whatever file I
designate. I'd rather not use this COM assembly, but would like to figure
out how to do this with the Win32 API.
Post by Dave O.
Which takes back to the start, as you cannot modify the originating
program you have to deal with the output which means getting at the print
data, which in turn means setting up a print DRIVER which prints to the
"Print to File" port.
This gives you 2 options,
1) Write a new driver which only prints to file - I suspect not possible
with VB, hopefully some one can prove me wrong on that but I wouldn't hold
my breath.
2) Force an existing printer driver to output to file and to a specific
file without popping up the "Output File Name" dialog which the existing
"Print to File" driver currently does. Again I don't know if there is a
To make the whole operation seamless write a launcher to run the existing
labeller program whose driver you've set to "Print to File", then the
launcher monitors what window is topmost, when the "Output File Name"
dialog pops up it uses SendMessage to fill in the file name and press the
OK button, this will happen in "the blink of an eye". The program also
monitors the folder where the file is to be written and as soon as the
file is available it can do whatever is needed then send the file to the
printer. This program should also monitor what programs are running so
when the labeller program is closed the launcher unloads itself.
That may seem complicated but each part is possible so bringing the lot
together should not be too hard, certainly easier than writing a new
printer driver.
Best wishes
Dave O.
Post by Terry Olsen
Exactly! Which is why I asked how to create a "Print To File" port
programmatically in the first place.
Post by Dave O.
Post by Terry Olsen
how do I go about intercepting the label data _before_ it's printed,
You don't, you print to file (or perhaps to stdout, no idea how but must
be possible) then process the data then print as usual.
The fun stars when you want all that to be automatic.
Regards
Dave O.
Post by Terry Olsen
Post by Dave O.
So you want to print to a file. A test first, if using the existing
printer driver (or the Generic/Text one) you select the "Print to
File" option is the file created adequate for your needs?
Because if it is, the solution of creating printer ports does seem a
bit excessive, all you need to do is get that file, process it and
then print it. I say "all", it is not exactly trivial but I'm sure it
can be done.
Tony Edgecombe
2007-02-24 09:09:32 UTC
Permalink
Post by Terry Olsen
Not to beat a dead horse, but I still haven't figured out how to do this
with the API. I did figure out how to do it using the PRNADMIN.DLL COM
Public Sub CreateFilePort(ByVal FilePath As String)
Dim PRNADMIN As New PRNADMINLib.PrintMaster
Dim port As New PRNADMINLib.Port
port.PortName = FilePath
port.PortType = 3 'Standard Local Port
PRNADMIN.PortAdd(port)
End Sub
You should use AddPortEx, the documentation says it is obsolete but it
does still work in all current versions of Windows.

Use a PORT_INFO_1 structure and pass the path as the port name.

Tony Edgecombe
www.printdistributor.com
Print redirection software
Terry Olsen
2007-02-24 23:40:45 UTC
Permalink
Do you happen to have an example. Here's what I tried and it didn't work. I
get the error shown below:

Public Structure PORT_INFO_1
Dim pPortName As String
End Structure

Public Declare Function AddPortEx Lib "winspool.drv" Alias "AddPortExA"
(ByVal pName As String, ByVal pLevel As Integer, ByVal lpBuffer As Object,
ByVal pMonitorName As String) As Integer

Dim PortInfo1 As PORT_INFO_1
PortInfo1.pPortName = FilePath
Dim x As Integer = AddPortEx(Nothing, 1, PortInfo1, "Local Port")
<--Exception thrown here

The error i'm getting is "Value does not fall within the expected range"

Looking for help getting this to work.
Post by Tony Edgecombe
Post by Terry Olsen
Not to beat a dead horse, but I still haven't figured out how to do this
with the API. I did figure out how to do it using the PRNADMIN.DLL COM
Public Sub CreateFilePort(ByVal FilePath As String)
Dim PRNADMIN As New PRNADMINLib.PrintMaster
Dim port As New PRNADMINLib.Port
port.PortName = FilePath
port.PortType = 3 'Standard Local Port
PRNADMIN.PortAdd(port)
End Sub
You should use AddPortEx, the documentation says it is obsolete but it
does still work in all current versions of Windows.
Use a PORT_INFO_1 structure and pass the path as the port name.
Tony Edgecombe
www.printdistributor.com
Print redirection software
J French
2007-02-25 07:15:24 UTC
Permalink
On Sat, 24 Feb 2007 16:40:45 -0700, "Terry Olsen"
Post by Terry Olsen
Do you happen to have an example. Here's what I tried and it didn't work. I
Public Structure PORT_INFO_1
Dim pPortName As String
End Structure
Public Declare Function AddPortEx Lib "winspool.drv" Alias "AddPortExA"
(ByVal pName As String, ByVal pLevel As Integer, ByVal lpBuffer As Object,
ByVal pMonitorName As String) As Integer
Dim PortInfo1 As PORT_INFO_1
PortInfo1.pPortName = FilePath
Dim x As Integer = AddPortEx(Nothing, 1, PortInfo1, "Local Port")
<--Exception thrown here
The error i'm getting is "Value does not fall within the expected range"
That Nothing should be vbNullString

Hang on this is VB.NET
- this is a VB 'Classic' NG you need to find a NG with dotnet in its
name
Terry Olsen
2007-02-25 20:30:37 UTC
Permalink
I got it to work. all I had to do was change the "ByVal lpBuffer As Object"
to "ByVal lpBuffer As PORT_INFO_1".

Sadly, there isn't a vb.net api newsgroup. I guess they think you don't need
the api if you're using .net. Sounds like a good reason to start my own news
server :)
Post by J French
On Sat, 24 Feb 2007 16:40:45 -0700, "Terry Olsen"
Post by Terry Olsen
Do you happen to have an example. Here's what I tried and it didn't work. I
Public Structure PORT_INFO_1
Dim pPortName As String
End Structure
Public Declare Function AddPortEx Lib "winspool.drv" Alias "AddPortExA"
(ByVal pName As String, ByVal pLevel As Integer, ByVal lpBuffer As Object,
ByVal pMonitorName As String) As Integer
Dim PortInfo1 As PORT_INFO_1
PortInfo1.pPortName = FilePath
Dim x As Integer = AddPortEx(Nothing, 1, PortInfo1, "Local Port")
<--Exception thrown here
The error i'm getting is "Value does not fall within the expected range"
That Nothing should be vbNullString
Hang on this is VB.NET
- this is a VB 'Classic' NG you need to find a NG with dotnet in its
name
unknown
2007-03-06 08:33:31 UTC
Permalink
I think, you will uncover more and more troubles along the way... For exemple, what about catching the original print outs in the Windows spooler folder ?

I know, i have been through this already : i work for a company that sells a standard software for thermal printers and for automated printing.

If i may give you an advice, you should check our Teklynx site for several 'of the shelf' solutions.


EggHeadCafe.com - .NET Developer Portal of Choice
http://www.eggheadcafe.com
NeilH
2007-03-06 13:18:09 UTC
Permalink
What are you replying to?
Post by unknown
I think, you will uncover more and more troubles along the way... For
exemple, what about catching the original print outs in the Windows spooler
folder ?
Post by unknown
I know, i have been through this already : i work for a company that sells
a standard software for thermal printers and for automated printing.
Post by unknown
If i may give you an advice, you should check our Teklynx site for several
'of the shelf' solutions.
Post by unknown
EggHeadCafe.com - .NET Developer Portal of Choice
http://www.eggheadcafe.com
Thorsten Albers
2007-02-07 15:02:47 UTC
Permalink
Post by Terry Olsen
I don't want to create a driver. I want to use the AddPort & AddMonitor API
functions to create a printer port that writes to a file. But I can find no
code examples on how to do this.
A printer port can't write to a file, a driver connected to a printer port
can. Therefore either you have to create a driver, or you have to use a
driver appropriate for your aim.
--
----------------------------------------------------------------------
THORSTEN ALBERS Universität Freiburg
albers@
uni-freiburg.de
----------------------------------------------------------------------
Continue reading on narkive:
Loading...