Version 35 of Printing text files under Windows

Updated 2004-03-22 09:25:01

Keith Vetter 2003-09-10: Today I wanted to print a simple text from within tcl. I thought it should be easy--it is just exec notepad /p myfile.txt. But to do it properly turned out to be quite difficult.

I'll explain why, but the ultimate command you need to executes is this:

   exec c:/winnt/system32/cmd.exe /c start /min c:/winnt/system32/notepad /p myfile.txt

First off, you need to look in the registry and find the print command for text files:

    package require registry
    set app [registry get {HKEY_CLASSES_ROOT\.txt} {}]
    set pcmd [registry get HKEY_CLASSES_ROOT\\$app\\shell\\print\\command {}]
      NB. pcmd => %SystemRoot%\system32\NOTEPAD.EXE /p %1

Now put our file name for %1.

    set fname myfile.txt
    regsub -all {%1} $pcmd [file normalize $fname] pcmd
      NB. pcmd => %SystemRoot%\system32\NOTEPAD.EXE /p c:/temp/myfile.txt

So far so good, but now when I try to execute it there are two problems. First, the %SystemRoot% needs to be handled, and second, the notepad window flashes momentarily. Luckily, both problems can be handled by simply using start /min to run the command.

     set command "[auto_execok start] /min $pcmd"
     exec $command &

WRONG -- this needs to be broken into words with eval

     eval exec $command &

WRONG -- the backslashes in $pcmd are doubly interpreted

     set command "[auto_execok start] /min [regsub -all {\\} $pcmd {\\\\}]"
     eval exec $command &

YEAH! (and don't try replacing the backslashes with forward slashes or 4DOS/4NT won't work)

Putting it all together, here's a short procedure to print a text file on windows (w/ no error checking and tested only on Win2k):

 proc PrintText {fname} {
    package require registry
    set app [registry get {HKEY_CLASSES_ROOT\.txt} {}]
    set pcmd [registry get HKEY_CLASSES_ROOT\\$app\\shell\\print\\command {}]
    regsub -all {%1} $pcmd [file normalize $fname] pcmd
    set command "[auto_execok start] /min [regsub -all {\\} $pcmd {\\\\}]"
    eval exec $command &
 }

This will not work on W2k, if pcmd contains spaces, and is quoted with "", as start will interpret it as the window title. (it works on Win9x). Adding a "" to the command line helps.

KPV could you explain your fix more. Or perhaps you could insert a dummy window title.

HZe I have had similar problems with the command start and the usage of quotes "". The most robust solution I found is to convert all filenames to Windows shortnames by

 set filename [file attribute $filename -shortname]

and don't include it in quotes. Otherwise I didn't get it to work on Windows NT, 2000 and XP.

schlenk I did check for NT and Win9x which don't interpret the first "" parameter to start as window title and W2k and up which do that and simply insert a dummy value if needed.Its braindead but documented in the help file of the start command...


See also: Tcl 9.0 WishList - #66.


AM kroc informed me about yet another utility that is available for this type of things: [L1 ]. Typical usage:

 [catch [ list exec printraw.exe [file nativename [file join $dir spoolout *.prn]] $printername ]]

KPV But the whole point of the above exercise was to ask the Windows OS how to print a text file. Theorectically it should work regardless of which utility is present or not.

AM I just (mis)used the page to document this utility - I could not find the other one. I quite appreciate this insight, as I have an immediate use for it!!

AM Can anyone shed light on the question how to achieve this on a Macintosh? (I do not have access to one, but I am interested to know how it would work there)

Lars H In Mac OS X there is a Unixy command enscript which can be used for this. Probably the traditional lp/lpr can be used as well (although these may in fact be using the enscript thing to do formatting and such). On Mac OS 9 you would probably have to do something along the lines above: starting "SimpleText" (or whatever it is called in English), tell it to open a new file, tell it to insert the text you want, and then tell it to print the thing; all via AppleEvents directly (e.g. using TclAE) or via Applescript (the Tclapplescript extension). If the text is already in a file it might however be easier to tell the Finder to print it, as that will then call upon the proper application to do the printing.


Also, check out http://sf.net/ project tclgdp which is a Tcl/Tk library and program to allow easy printing to the Nintendo Gameboy Printer from a PC.


[Peter Newman 21 March 2004: The simplest way to print a text file on Windows is to go:-

 type d:\path\to\myfile.txt > prn

from the DOS prompt. "Type" prints the specified file to stdout (by default). It's the DOS equivalent to Unix's CAT. The "> prn" re-directs output to the default printer.

So from Tcl:-

 exec $env(COMSPEC) /c type [file attribute d:\path\to\myfile.txt -shortname] > prn

should work on ALL versions of DOS and Windows. COMSPEC is an environment variable that I understand is available on all versions of Windows and points to the DOS shell (typically either COMMAND.COM or CMD.EXE). And we convert the file to 8.3 form so that it will work even on DOS systems that don't support long filenames.

Unfortunately, the above doesn't work. Exec complains:-

 Can't execute "c:\windows\command.com": no such file or directory.

But c:\windows\command.com (which is what $env(COMSPEC) evaluates to on my system) DOES exist. So either I've wired up the call to exec wrong - or exec has a bug in it. I couldn't be bothered trying to figure exec out (as you can see from all the ifs, but and maybes in the man page - and from the discussion above, that command is a bug-ridden disaster that needs a LOT more work). Use winutils launch or shell instead, and it'll work.

The difference between the "notepad /p myfile.txt" and "type myfile.txt > prn" methods is that "type myfile.txt > prn" sends output directly to the printer in 10 CPI ASCII mode. It by-passes the Windows printer driver. So it's fast (printing starts immediately). But the font is quite large - so you waste lots of paper. The "notepad /p myfile.txt" method uses the Windows printer driver. So there's a 3 year delay before printing starts - but the font used is usually smaller. Hence less wasted paper.


KPV On my Win2k with a local Canon printer this doesn't work--the command returns immediately but comes out on the printer. Also, I have my doubts on how this would work with a network printer.


Peter Newman 21 March 2004: Yeah! The point I was trying to make was that the STANDARD way to print a text file from DOS/Windows is to go:-

 type d:\path\to\myfile.txt > prn

from the DOS prompt.

I know that works on any version of DOS (from 2.00 upwards) and Windows 95/98 (because I've done it a million times). I ASSUME it'll also work on Windows 2000/NT and XP. But maybe not. Did you try typing the above from the DOS prompt?

It also works just fine with Perl's system command (on DOS and Windows 95/98). But it doesn't work with Tcl's exec. The problem is with exec (and/or the way we're calling it). Use winutils instead.

It should work with network printers too. But they have to be set up right. Usually PRN points to the DOS/Windows default printer. And LPT1 is a synonym for PRN. And LPT2 to LPT4 point to any other printers you may have. But you'll have to check your DOS/Windows documentation for the details - especially how configure them to point to your network printers. I've never myself tried this with network printers - though I'm sure it can be done.

KPV Sorry, I was unclear: the command fails for me even from the command prompt. Win95/98 are radically different than win2k and XP--they're really just a shell on top of command.com--so I'm NOT surprised it doesn't work.


Peter Newman: If in doubt, read the manual I went to the Microsoft web site and looked at the Win2000 manual. And sure enough it has a TYPE command. But that command DOESN'T support re-direction to printers. Instead, there's PRINT command for printing text files to printers. And that PRINT command supports both local and network printers.

So to summarise! To print a text file under DOS/Windows from the DOS prompt (and assuming that Win 2K, NT and XP all work the same):-

 type  d:\path\to\myfile.txt > prn      # DOS and Windows 9x
 print d:\path\to\myfile.txt            # Win 2K (and presumably also NT and XP)

And since anything you can do from the DOS prompt, you should also be able to do with exec, you should also be able to do those from Tcl.

Also, I don't think it's true that Win 2K, NT and XP are radically different from DOS and Win 9x. Win 2K, NT and XP support basically the same DOS commands as Win 9x. But there are some minor differences - as with TYPE/PRINT described above. And there are a whole load of new network/Internet related commands - to give the Win 2K, NT and XP command prompt a lot more Unix like power. KPV The difference between Win95/98 and WinNT/2K/XP is that the former uses DOS as it's underlying OS while the latter is a totally new OS written from scratch.

Note also that:-

  1. Under DOS and Windows 9x you can also use:-
 COPY /b d:\path\to\myfile.txt prn
  1. The PRINT differs from TYPE and COPY is that it maintains a background print spooler. So it's slower.
  2. The printer support in TYPE and COPY (under DOS and Windows 9x) stems from the days where printers where connected to the PARALLEL port. Nowadays, most printers are USB or network connected. So even under DOS and Windows 9x, you won't be able to TYPE or COPY to a USB or network printer unless the OS concerned supports them.
  3. PRINT is also available under Windows 9x and DOS. I've got a DOS version 4.00 manual that lists it.
  4. Looking on the Internet I found references to the fact that Win 2K, NT and XP have a 15 second delay before printing starts - which fools some people into thinking nothing's happening. Apparently it can be fixed - and Microsoft have details on how to do this.

So to SUMMARISE (again)! To print a text file under DOS/Windows:-

 Go to your DOS Prompt Reference Manual and check out the:-
  • TYPE
  • COPY and;
  • PRINT
 commands. Then use whichever works (on your system).

But note that:-

  1. The alternative method of using "NOTEPAD /P" (discussed above), has the advantage of using smaller font sizes. So it usually looks better - and wastes less paper.
  2. COPY, TYPE and PRINT generally wrap long lines automatically. So they're usually the best solution for PROGRAM LISTINGS. NOTEPAD usually silently truncates long lines (which is irritating/dangerous with program listings).
  3. NOTEPAD (at least the Windows 95 versions of it,) can't handle Unix and Mac text files. It usually sees them as one long line. A major PITA. It may be the same with COPY, TYPE and PRINT. Whether the later versions of Windows are more Unix/Mac friendly I don't know. So you may have line ending translation issues to worry about too.
  4. Another Windows text file printing option to check, is winutils::shell winutils. This supports the "print" option - which looks to me like the Bill-Gates-approved method of printing things from Windows. :-(
  5. Another useful hack for printing text files under Windows, is to load them into your Web Browser, wrapped in <PRE>...your text file here...</PRE> tags. You should then be able to scale the font size down quite easily. And print it quite easily too. And most browsers support Unix and Mac line terminators too. The only problem is that long lines (if you have them,) will be truncated.

KPV Sorry, once again this doesn't work for me under Win2k. The print command is just a spooler for copying files to the parallel port and that just doesn't work. For a printing utility I maintain, I found that for network printers I had to open a socket to connect to it. I suspect my home printer doesn't understand straight ASCII but wants it own protocol (what you see when you say print to a file).


Peter Newman: OK, I see it's not working for you. But I didn't want users un-familiar with Windows to think that it's difficult or impossible to print text files from Windows. It isn't. It's a pice of cake, no matter which version you're using. You just use the TYPE, COPY and/or PRINT command(s) applicable to your version of Windows. And if the Windows version is network-aware, they'll print to both local and network printers too.

I know that's definitely true with DOS 2.00 to Windows 9x. And I just spent more time on the Microsoft web-site to check out 2K, NT and XP. They all support TYPE, COPY and PRINT - except perhaps NT - where PRINT may be missing and you use COPY instead. And all of 2K, NT and XP support both local and network printers.

As regards Windows 2K, see the "Print" command in the "Windows 2000 Command Reference" and "154498 - How to Print to Network Printer from MS-DOS-Based Programs".

So if it doesn't work for you, the problem must be with your installation - not with Win 2K generally. But printer problems are hardly un-usual. If you haven't had those, you've never owned a printer. With 2K, NT and XP, I noticed a zillion articles on the Microsoft web site re. printer problems. If you'd like to upgrade to a decent bug-free O/S, I've got some old copies of MS-DOS 2.00. No network printing problems guaranteed (it doesn't support LANS)! Regards.


Category Printing