In this article, I'll discuss how you can use a batch script to map a client's redirected printer to LPT1: automatically. This can help your DOS programs in a terminal services session if they can't work with terminal services redirected printers, but they can see the LPT ports.
Prerequisites:
•The script, which can be downloaded here or at the end of this article.
•Read Microsoft Knowledgebase Article 189105
•A terminal server that you have administrator access to. This script works with Windows 2000 and Windows Server 2003.
•Because this script requires the user to create a printer share, increased privileges may be required. Use of the RunAs command is recommended.
For this tutorial, I'm going to step through the script to explain what happens.
Section 1: Headers:
SetLocal
Set ShareName=RedirPr
Set UniqueID=1
Sleep 15
Basically, all I'm doing here is forcing the script to localize all these variables within this script.
Localizing the variables isn't absolutely necessary, but this helps to prevent variables from mixing up between your scripts, especially if you merge this script with other scripts.
The sleep utility (which is included in the script download) is there just to force the script to wait a little while during the initial logon sequence. Since the terminal server can take a few seconds to map the client printers, the pause is just there to make extra sure that the terminal server is done mapping printers. If the sleep command wasn't there, then we risk having this script run and terminate before the terminal server is completely done mapping printers.
If this script wasn't run during the logon, then the sleep command could be removed.
Section 2: Query the registry:
"%SystemRoot%\Application Compatibility Scripts\acregl.exe" DefPrint.cmd DefaultPrinter "HKCU\Software\Microsoft\Windows NT\CurrentVersion\Windows" "Device" ""
If Not Exist DefPrint.cmd (Call :Error 1 1) && (Goto EoF)
call DefPrint.cmd
del DefPrint.cmd
If Not Defined DefaultPrinter (Call :Error 2 1) && (Goto EoF)
This command uses the built in AcRegl.exe command to query the registry for a particlar value. In this case, we are looking for the Device value at HKCU\Software\Microsoft\Windows NT\CurrentVersion\Windows.
That value will be set to equal the variable DefaultPrinter in the rest of our script.
The If statement checks to make sure the AcRegl.exe command executed properly, and the subsequent call and del commands set the DefaultPrinter variable.
If everything has gone right, the DefaultPrinter variable will equal something like: HP DeskJet 820CSe/ComputerName/Session 1,winspool,TS001. The last If statement checks to make sure the DefaultPrinter variable is set; if it isn't then the Error portion of the script script is called and the script quits.
Section 3: Parse the DefaultPrinter variable:
for /f "tokens=1 delims=," %%i in ('"echo %DefaultPrinter%"') do set PrinterString=%%i
This For command parses the DefaultPrinter variable. It obtains the printer's name only, which will result in: HP DeskJet 820CSe/ComputerName/Session 1. It essentially removes the ',winspool,TS001' portion of the DefaultPrinter variable.
Section 4: Get the session number:
For /f "tokens=3" %%j in ('qwinsta ^| find "%username%"') do set SessionNum=%%j
If Not Defined SessionNum (Call :Error 3 1) && (Goto EoF)
If %SessionNum% LSS 0 (Call :Error 4 %SessionNum%) && (Goto EoF)
If %sessionNum% GTR 65535 (Call :Error 5 %SessionNum%) && (Goto EoF)
The For command obtains the current user's session number and stores it in the SessionNum variable. The next three If statements just verify that the number we obtained for the SessionNum variable is a valid number. If it isn't valid, then we call the Error printing function and the script exits.
Section 5: Check the LPT port:
net use lpt1:
if %ERRORLEVEL% EQU 0 net use lpt1: /d
Since we are now almost ready to map the printer to the LPT1 port, we make a check here to make sure that nothing else is using the LPT1: port. If something is, then we try to unmap it so we can map our printer to it. Users of this script may want to edit these lines, since they may want to print to LPT2: rather than LPT1:.
Section 6: Create a unique mapping name:
:CheckShare
for /f %%k in ('net share ^| find /c /i "%ShareName%_%SessionNum%_%UniqueID%"') do set var=%%k
if %var% NEQ 0 (set /a UniqueID=%UniqueID%+1) && (goto CheckShare)
Set ShareName=%ShareName%_%SessionNum%_%UniqueID%
This small set of commands checks to make sure we have a unique name for our printer mapping. Since this script takes the default printer, creates a share for it, then maps LPT1: to it, we need to make sure the share name is unique.
Section 7: Map the printer to LPT1::
rundll32 printui.dll,PrintUIEntry /Xs /n "%PrinterString%" sharename %ShareName% attributes +Shared
net use lpt1: \\127.0.0.1\%ShareName% /persistent:no
if %ERRORLEVEL% NEQ 0 (Call :Error 6 1) && (Goto EoF)
The title says it all. The rundll32 command shares the printer out, the net use command maps the shared printer to LPT1: and the If command makes sure everything worked right. If everything has worked right, the script will then terminate.
Section 8: Cleanup before we exit:
EndLocal
Goto EoF
:Error
msg %SessionName% /W Your printers were not successfully mapped to the LPT1 port. Please notify an administrator. (Error Code: %1 %2)
EndLocal
Goto EoF
:EoF
As the script exits, it terminates variable localization using the EndLocal command. However, as stated earlier, if a problem has occurred somewhere in the above script, then the :Error section will be called, which basically just prints out an error message to the user, along with an error code to help an admin troubleshoot the script.
Well, that's about it. You've just finished a walkthrough tutorial for this script.
And...no tutorial would be complete without a download, so here is the script in its entirety (compressed):
Printer.zip
|