Rob van der Woude's Scripting Pages

Print Files from Batch Files

Print Text Files

In Windows, ASCII files can be printed using the "classic" PRINT command:

PRINT mytext.txt /D:LPT2

By default, PRINT will send its output to LPT1.
By using the /D switch, a different printer port can be used.

On most modern computers, PRINT will be useless, because it needs a printer port like LPT1 or COM1 etc., whereas most printers nowadays are connected either to USB ports or over a TCP/IP connection.

In those cases, a better alternative to the PRINT command is Notepad with its /P switch:

NOTEPAD /P whatever.reg

will print whatever.reg, even if .REG files aren't associated with Notepad at all (by default they aren't, and they shouldn't be).

Notepad will send its output to Windows' default printer.

Likewise, Wordpad can print plain text as well as rich text using its /P switch:

WORDPAD /P whatever.rtf

will open whatever.rtf in Wordpad and then open the "Print" dialog.

Unlike Notepad, Wordpad does have a /PT switch:

WORDPAD /PT whatever.rtf MyPrinter

will open whatever.rtf in Wordpad, print whatever.rtf on the printer named MyPrinter and then close Wordpad again.

Print Registered File Types

Files that have a file type association in Windows (95/98/NT/2000) can be printed using the right mouse button (assuming you didn't swap mouse buttons).
However, most visitors to this site are probably more interested in using the command line instead of the GUI.
On this page I will explain how you can use the file association to print a file from the command line.
There is a limitation to this technique, however: for most file types, "Print" opens Windows' print dialogue for the file, so the user still has to click the "Print" or "OK" button. Usually, "PrintTo" commands are executed without user interaction, but they do require a printer name as their second command line argument.

PrintHTM.bat

When you start Windows' Explorer and click the "View" menu entry, then "Options...", and choose the "File Types" tab, you will see a list of all file types with their associations.
If it was just the associations we were after, we could have used ASSOCIATE.EXE from the Resource Kit, but in this case we are more interested in the print commands.

Scroll through the list and select "HTML Document".
Depending on your Windows version, click the "Advanced" or "Edit" button.
In the "Actions" list you should now see at least these 3 options:

Edit
open
print

The option in bold face is the one started when you double-click a file of this type.

Select "print" and click the "Edit" button beside or below the "Actions" list.
This will open a dialogue titled "Edit action for type: HTML Document".
It is the value of the field "Application used to perform action" that we are after.
On most systems it will read something like this:

rundll32.exe C:\WINDOWS\System\mshtml.dll,PrintHTML "%1"

or:

rundll32.exe C:\WINNT\System32\mshtml.dll,PrintHTML "%1"

Since the directory for the DLL is where RUNDLL32.EXE will look by default, we can leave it out to make the command more generic:

RUNDLL32.EXE MSHTML.DLL,PrintHTML "%1"

This command can be used to print HTML files from a batch file.
The following example is NT only, but with a few modifications it can be used in Windows 95/98 as well. Do not expect these modifications to be easy reading, though.

@ECHO OFF
SETLOCAL

:: Command line parsing
SET File2Print=%*
ECHO.%File2Print% | FIND "?" >NUL
IF NOT ERRORLEVEL 1 GOTO Syntax
:: Strip leading space in NT 4 only
VER | FIND "Windows NT" >NUL
IF NOT ERRORLEVEL 1 IF DEFINED File2Print SET File2Print=%File2Print:~1%
IF DEFINED File2Print SET File2Print=%File2Print:"=%
IF NOT DEFINED File2Print GOTO Syntax
IF NOT EXIST "%File2Print:"=%" GOTO Syntax

:: Actual print command
RUNDLL32.EXE MSHTML.DLL,PrintHTML "%File2Print%"

:: Done
GOTO End

:Syntax
ECHO.
ECHO PrintHTM.bat,  Version 1.11 for Windows NT
ECHO Prints a local HTML file from the command line
ECHO.
ECHO Written by Rob van der Woude
ECHO http://www.robvanderwoude.com
ECHO.
ECHO Usage:  %~n0  ^<html_file^>

:End
ENDLOCAL

 

Click to view source Click to download the ZIPped sources

PrintPDF.bat

Now that one was easy, using RUNDLL32 and an almost (!) native DLL.
How about PDF files, for example?
Can a batch file for printing PDF files be made generic enough to cope with different installations and versions of Adobe Acrobat Reader?

You may have guessed: I wouldn't have asked if the answer had been NO.

Note: There is one restriction, though: this batch file will only work when PDF files' default association is any Acrobat Reader version.
This means that if you have Acrobat Writer installed on your PC, this batch file will fail.
As of version 1.20 a message will be displayed to explain why it fails. Thanks to Chuck Hicks for this addition.
Thanks to Michael Lintner for his modification to enable long file names.
Thanks to Fabio Quieti for adding the /T switch, which automatically closes the Adobe Reader window after printing the file (note: this /T switch has only been tested with Adobe Reader 7).

By using ASSOC, FTYPE and REGEDIT to read the PDF print command from the registry we can print PDF files from within batch files:

@ECHO OFF
:: Check Windows version, abort if not NT 4 or later
IF NOT "%OS%"=="Windows_NT" GOTO Syntax
SETLOCAL ENABLEDELAYEDEXPANSION

:: Initialize variables
SET PrintCmd=
SET Temp=%Temp:"=%
SET NumFiles=0
SET MultiPrint=0
SET ListTool=

:: Check command line arguments
IF     "%~1"=="" GOTO Syntax
IF NOT "%~3"=="" GOTO Syntax
IF     "%~2"=="" (
	SET FileSpec=%~1
) ELSE (
	IF /I "%~1"=="/M" SET FileSpec=%~2
	IF /I "%~2"=="/M" SET FileSpec=%~1
)
ECHO.%* | FIND /I "/M" >NUL && SET MultiPrint=1
ECHO.%FileSpec% | FIND "/" >NUL && GOTO Syntax
IF NOT EXIST "%FileSpec%" GOTO Syntax

:: Count the number of files specified by filespec
FOR %%A IN (%FileSpec%) DO SET /A NumFiles = !NumFiles! + 1
IF %NumFiles% EQU 0 GOTO Syntax

:: Check if we need to have access to a list of processes
:: currently running, and if so, which one is available
IF %NumFiles%   GTR 1 SET  MultiPrint=1
IF %MultiPrint% EQU 0 CALL :GetListTool

:: Get the file association from the registry
FOR /F "tokens=1* delims==" %%A IN ('ASSOC .PDF') DO (
	FOR /F "tokens=1 delims==" %%C IN ('FTYPE ˆ| FIND /I "%%~B"') DO (
		CALL :GetPrintCommand %%C
	)
)

:: Check if a print command was found
IF NOT DEFINED PrintCmd (
	ECHO.
	ECHO No print command seems to be associated with .PDF files on this computer.
	GOTO Syntax
)

:: Print the file using the print command we just found
FOR %%A IN (%FileSpec%) DO CALL :ExecPrintCommand "%%~fA"

:: A final message
IF "%MultiPrint%"=="1" (
	ECHO.
	ECHO You will need to close the Acrobat Reader window manually after the printing
	ECHO is finished.
	IF "%NumFiles%"=="1" IF "%ListTool%"=="" (
		ECHO To close that window automatically next time you print a single PDF file,
		ECHO download and install PSLIST from the Microsoft website:
		ECHO https://technet.microsoft.com/en-us/sysinternals/pstools	)
)

:: Done
GOTO End


:ExecPrintCommand
CALL echo START /MIN "PrintPDF" %PrintCmd%
GOTO:EOF


:GetListTool
:: Now we need to find a tool to check for processes.
:: In XP and later this will be the native TASKLIST command,
:: in NT 4 and 2000 we'll need to find a non-native tool.
:: First we'll try TASKLIST ...
TASKLIST >NUL 2>&1
IF ERRORLEVEL 1 (
	REM ... if TASKLIST isn't available we'll try TLIST next ...
	TLIST >NUL 2>&1
	IF ERRORLEVEL 1 (
		REM ... and if that isn't available either we'll try PSLIST ...
		PSLIST >NUL 2>&1
		IF NOT ERRORLEVEL 1 SET ListTool=PSLIST
	) ELSE (
		SET ListTool=TLIST
	)
) ELSE (
	SET ListTool=TASKLIST
)
:: Don't worry if we didn't find ANY tool to list processes, in
:: that case we'll just assume multiple PDFs need to be printed
IF "%ListTool%"=="" SET MultiPrint=1
GOTO:EOF


:GetPrintCommand
:: Get the print command for this file type from the registry
START /WAIT REGEDIT.EXE /E "%Temp%.\pdf.dat" "HKEY_CLASSES_ROOT\%1\shell\print\command"
IF NOT EXIST "%Temp%.\pdf.dat" GOTO:EOF
FOR /F "tokens=1* delims==" %%D IN ('TYPE "%TEMP%.\pdf.dat" ˆ| FIND "@="') DO SET PrintCmd=%%E
DEL "%Temp%.\pdf.dat"
SET PrintCmd=%PrintCmd:\"="%
SET PrintCmd=%PrintCmd:""="%
SET PrintCmd=%PrintCmd:\\=\%
:: The /T switch terminates Acrobat Reader after printing.
:: Thanks to Fabio Quieti for sending me this tip.
:: However, as Michael Butler pointed out, it should not be
:: used when printing lots of files.
:: So I introduced a /M switch for this batch file, stating
:: that multiple files are to be printed.
:: Without specifying the /M switch, this will also be true
:: when wildcards are used in the filespec.
:: Finally, if another Adobe Reader process is running right
:: now, we won't be using the /T switch either.
IF %MultiPrint% EQU 0 CALL :CheckProcess %PrintCmd%
IF %MultiPrint% EQU 0 (
	SET PrintCmd=%PrintCmd:"%1"=/t "%%%~1"%
	rem SET PrintCmd=%PrintCmd% /t "%%~1"
) ELSE (
	SET PrintCmd=%PrintCmd:"%1"="%%%~1"%
	rem SET PrintCmd=%PrintCmd% "%%~1"
)
GOTO:EOF


:CheckProcess
IF "%ListTool%"=="" (
	SET MultiPrint=1
) ELSE (
	%ListTool% 2>&1 | FIND /I "%~n1" >NUL && SET MultiPrint=1
)
GOTO:EOF

:Syntax
ECHO.
ECHO PrintPDF.bat,  Version 3.10 for Windows NT 4 / 2000 / XP / Server 2003
ECHO Prints PDF files from the command line
ECHO.
ECHO Usage:  PRINTPDF  pdf_filespec  [ /M ]
ECHO.
ECHO Where:  "pdf_filespec"  is the file name or filespec of the PDF file(s)
ECHO                         to be printed; wildcards allowed (*); use double
ECHO                         quotes for long file names
ECHO.
ECHO Notes:  This batch file has been tested with Acrobat Reader versions 5-7 only.
ECHO         It requires Adobe/Acrobat Reader, and will NOT work if Acrobat "Writer"
ECHO         is installed.
ECHO         Thanks to Fabio Quieti, as of version 3.00, you no longer need to close
ECHO         the minimized Acrobat Reader window manually, after printing the file.
ECHO         Thanks to Michael Butler, printing lots of PDFs will no longer make the
ECHO         computer slow down to a crawl or even hang.
ECHO.
ECHO Written by Rob van der Woude
ECHO http://www.robvanderwoude.com


:End
IF "%OS%"=="Windows_NT" ENDLOCAL

A note by Michael Butler on printing lots of PDFs from the command line:

I think your PDF printing methods listed may not work well for a list of over 50 PDFs. I had a script using

CALL START /MIN AcroRd32.exe /h /p [filename]

for each PDF in a list, but it stopped queuing them up at about the 35th-50th one (had a list of 90), depending on the computer. I think it is related to how memory is allocated with CALL START.
After a lot of troubleshooting, I found that you can FIRST launch Adobe Reader using

CALL START /MIN AcroRd32.exe /h

and then later in the script just call (without using CALL START)

AcroRd32.exe /h /p [filename]

for each file name, and it will allow execution to return to the batch file because Adobe Reader is already open. This worked well for printing/queuing up over 100 PDFs.

I tried your recent /T switch option for Reader 7 and it seemed to open a new instance of AcroRd32.exe for every PDF - not feasible when printing more than 10 PDFs. The downside is that without /T, one instance of AcroRd32.exe will still be left open after the script ends, albeit minimized.

Well, I think I may have solved this dilemma by adding "a little bit" of extra code to the batch file.
As of version 3.10, a /M switch can be used to tell PrintPDF.bat that multiple batch files will be printed. In that case, the /T switch for the Acrobat/Adobe Reader will not be added, and the window will not be closed automatically, but at least all printing will be done in a single "instance" of the Reader.
Also added in this version: support for wildcards. The batch file will check if the wildcards translate into multiple files, and, if so, won't use the /T switch either.
Finally, a piece of code was added to check if an Acrobat Reader window is open, and, if so, assume multiple PDF printing again. To make this work in Windows NT 4 or 2000 requires some "third party" software. If necessary, the batch file will display a message where to download this software, and in the mean time it will assume multiple file printing (leaving the window open after printing).

So, to automatically close the Adobe/Acrobat Reader window after printing, the following requirements must all be met:

 

Click to view source Click to download the ZIPped sources

 

Explanation of PrintPDF.bat:

 

This code has also been "translated" into KiXtart, Perl, Rexx and VBScript versions (without the /T switch, this will follow soon).

 

A better VBScript version, by Charles Hicks, is available at Planet PDF.

PrintHTM.bat, Version 2.00

Next, a new version of PrintHTM.bat, which skips the printer dialog windows (using KiXtart's SendKeys( ) function) and accepts a printer name for its second command line parameter:

@ECHO OFF
SETLOCAL

:: Command line parsing
ECHO.%* | FIND "?" >NUL
IF NOT ERRORLEVEL 1 GOTO Syntax
ECHO.%* | FIND "*" >NUL
IF NOT ERRORLEVEL 1 GOTO Syntax
IF NOT [%3]==[] GOTO Syntax
:: Check first parameter (file to be printed)
SET File2Print=%1
IF NOT DEFINED File2Print GOTO Syntax
SET File2Print=%File2Print:"=%
SET File2Print="%File2Print%"
IF NOT DEFINED File2Print GOTO Syntax
IF NOT EXIST "%File2Print:"=%" GOTO Syntax
:: Check second parameter (printer)
SET Printer=%2
IF NOT DEFINED Printer GOTO Print
SET Printer=%Printer:"=%
SET Printer="%Printer%"
REGEDIT /E %TEMP%.\%~n0.dat "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Printers"
TYPE %TEMP%.\%~n0.dat | FIND "[" | FIND /I %Printer% >NUL
IF ERRORLEVEL 1 (
	ECHO Invalid printer name, using default printer
	SET Printer=
)
DEL %TEMP%.\%~n0.dat

:: Create temporary Kix file to "press" Print button
> %TEMP%.\%~n0.kix ECHO.; Wait a few seconds for the Print dialog to appear
>>%TEMP%.\%~n0.kix ECHO SLEEP 2
>>%TEMP%.\%~n0.kix ECHO.; Press "Print" (Enter) using SendKeys function
:: Replace "Print" with the actual title of the
:: Print dialog for non-US Windows versions
>>%TEMP%.\%~n0.kix ECHO IF SETFOCUS( "Print" ) = 0
>>%TEMP%.\%~n0.kix ECHO    $RC = SENDKEYS( "{ENTER}" )
>>%TEMP%.\%~n0.kix ECHO ENDIF

:Print
:: Actual print command
START RUNDLL32.EXE MSHTML.DLL,PrintHTML %File2Print% %Printer%

:: Call temporary Kix file to "press" Print button, then delete it
START /WAIT KIX32.EXE %TEMP%.\%~n0.kix
DEL %TEMP%.\%~n0.kix

:: Done
GOTO End

:Syntax
ECHO.
ECHO PrintHTM.bat,  Version 2.00 for Windows NT 4 / 2000
ECHO Prints a local HTML file from the command line
ECHO.
ECHO Usage:  %~n0  ˆ<html_fileˆ>  [ ˆ<printerˆ> ]
ECHO.
ECHO Use quotes around the file and printer names if they contain spaces.
ECHO This version uses Kix's SendKeysˆ( ˆ) function to "press" the Print
ECHO button in the Print dialog. Make sure that you have Kix installed on
ECHO your system and that KIX32.EXE can be found in the PATH.
ECHO Modify this batch file if you are using a non-US Windows version
ECHO ˆ(read the comment lines for more informationˆ).
ECHO.
ECHO Written by Rob van der Woude
ECHO http://www.robvanderwoude.com

:End
ENDLOCAL

 

Click to view source Click to download the ZIPped sources

PrintAny.bat, Version 2.01

Finally, a version that will print any known file type by using the associated print command from the registry.

@ECHO OFF
:: For Windows NT 4 or later only
IF NOT "%OS%"=="Windows_NT" GOTO Syntax

:: Localize variables
SETLOCAL
SET PrintCmd=
SET FileType=
SET Temp=%Temp:"=%

:: Command line parsing
IF NOT "%~2"=="" GOTO Syntax
IF     "%~1"=="" GOTO Syntax
IF    "%~n1"=="" GOTO Syntax
IF    "%~x1"=="" GOTO Syntax
ECHO."%~1" | FIND "/" >NUL && GOTO Syntax
ECHO."%~1" | FIND "?" >NUL && GOTO Syntax
ECHO."%~1" | FIND "*" >NUL && GOTO Syntax
IF NOT EXIST "%~1" GOTO Syntax

:: Get the file association from the registry
FOR /F "tokens=1* delims==" %%A IN ('ASSOC %~x1') DO (
	FOR /F "tokens=1 delims==" %%C IN ('FTYPE ^| FIND /I "%%~B"') DO (
		CALL :GetPrintCommand %%~C
	)
)

:: Check if a print command was found
IF NOT DEFINED PrintCmd GOTO NoAssoc

:: Print the file using the print command we just found
CALL START /MIN "PrintAny" %PrintCmd%

:: Done
GOTO End


:GetPrintCommand
:: Get the print command for this file type from the registry
FOR /F "tokens=3*" %%D IN ('REG.EXE Query HKCR\%1\shell\print\command /ve 2^>NUL') DO SET PrintCmd=%%E
IF NOT DEFINED PrintCmd GOTO:EOF
:: "Unescape" the command
SET PrintCmd=%PrintCmd:\"="%
SET PrintCmd=%PrintCmd:""="%
SET PrintCmd=%PrintCmd:\\=\%
:: Remove double double quotes in file name if applicable
ECHO.%PrintCmd% | FINDSTR.EXE /R /C:"\"%%1\"" >NUL && SET PrintCmd=%PrintCmd:"%1"="%%%~1"%
GOTO:EOF


:NoAssoc
CLS
ECHO.
ECHO Sorry, this batch file works only for known file types with associated
ECHO print commands defined in the registry hive HKEY_CLASSES_ROOT.
ECHO No print command seems to be associated with %~x1 files on this computer.
ECHO.


:Syntax
ECHO.
ECHO PrintAny.bat,  Version 2.01 for Windows 7 and later
ECHO Prints any known file type from the command line
ECHO.
ECHO Usage:  PRINTANY  file_to_print
ECHO.
ECHO Where:  "file_to_print"  is the name of the file to be printed
ECHO                          (use double quotes for long file names)
ECHO.
ECHO Notes:  For this batch file to work, the file type's print command has
ECHO         to be defined in the registry hive HKEY_CLASSES_ROOT, and that
ECHO         print command must NOT use DDE for printing.
ECHO         Unfortunately, most Office file types use DDE and hence won't
ECHO         print with this batch file.
ECHO.
ECHO Written by Rob van der Woude
ECHO http://www.robvanderwoude.com

:End
IF "%OS%"=="Windows_NT" ENDLOCAL

 

Click to view source Click to download the ZIPped sources

Parameters in File Associations

Often we find "%1" in the commands associated with file types (HKEY_CLASSES_ROOT\FileType\shell\open\command).
In Windows 9x through 2000 (and possibly XP) this would evaluate to the short notation of the fully qualified path of the file of type FileType.
To get the long file name, use "%L" instead of "%1".

I ran some tests in Windows 7 and found the following parameters for file associations:

Parameter Evaluates to
%1 Long fully qualified path of file
%D Long fully qualified path of file
%H 0
%I :number:number
%L Long fully qualified path of file
%S 1
%V Long fully qualified path of file
%W Long fully qualified path of parent folder

So far I don't have a clue as to what %H, %I and %S are for.
And it seems we can no longer get a short file name even if we want to.
For backward compatibility it would seem prudent to stick with %1, %L and %W (though I haven't tested %W in older Windows versions yet).

Or were you looking for this...?


page last modified: 2016-09-19; loaded in 0.0017 seconds