Version 14 of Printing text files under Windows

Updated 2004-01-16 18:17:36

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.


Category Printing