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:-
COPY /b d:\path\to\myfile.txt prn
So to SUMMARISE (again)! To print a text file under DOS/Windows:-
Go to your DOS Prompt Reference Manual and check out the:-
commands. Then use whichever works (on your system).
But note that:-
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. 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.