Rob van der Woude's Scripting Pages
Powered by GeSHi

Source code for print2.vbs

(view source code of print2.vbs as plain text)

  1. Option Explicit
  2.  
  3. Dim arrDummy, arrPrinters
  4. Dim blnDebug, blnPause
  5. Dim i, intBreak, intValidArgs, lngDelay
  6. Dim objFSO, objReg, wshShell
  7. Dim strDefaultPort, strDefaultPrinter, strNewDev, strOldDev
  8. Dim strCmdLine, strHive, strKeyPath, strKeyDescr, strPrnStr
  9. Dim strKeyStroke, strMsg, strRegVal, strScriptName
  10.  
  11. Const HKCU = &H80000001
  12.  
  13. ' Set blnDebug True to display intermediate results
  14. blnDebug      = False
  15. blnPause      = False
  16. intBreak      = 0
  17. intValidArgs  = 0
  18. lngDelay      = 0
  19. strHive       = "HKEY_CURRENT_USER\"
  20. strKeyPath    = "Software\Microsoft\Windows NT\CurrentVersion\"
  21. strKeyStroke  = ""
  22. strMsg        = ""
  23. strRegVal     = "HKCU\Software\Microsoft\Windows NT\CurrentVersion\Windows\Device"
  24. strScriptName = ""
  25.  
  26. ' Connect to the registry using WMI; this is necessary to
  27. ' enumerate keys, which cannot be done with the wshShell object
  28. Set objReg = GetObject( "winmgmts:{impersonationLevel=impersonate}!//" _
  29.                       & "./root/default:StdRegProv" )
  30. ' Query the list of printers
  31. objReg.EnumValues HKCU, strKeyPath & "PrinterPorts", arrPrinters, arrDummy
  32. Set objReg = Nothing
  33.  
  34. ' Abort if the list of printers is empty; intBreak will
  35. ' show where the script aborted in debugging mode
  36. intBreak = 1
  37. If Not IsArray( arrPrinters ) Then Syntax
  38.  
  39. ' Parse the command line
  40. With WScript.Arguments
  41. 	' Debugging information
  42. 	If blnDebug Then
  43. 		strMsg = "Command Line Arguments    : " & .Count & vbCrLf
  44. 		For i = 0 To .Count - 1
  45. 			strMsg = strMsg & "Command Line Argument " _
  46. 			                & Right( "  " & i, 3 ) _
  47. 			                & " : " & .Item(i) & vbCrLf
  48. 		Next
  49. 		strMsg = strMsg & vbCrLf
  50. 	End If
  51. 	intBreak = 2
  52. 	' At least 2 arguments are required
  53. 	If .Count < 2 Then Syntax
  54. 	strMsg = strMsg & vbCrLf & "Available printers        : " _
  55. 	                & UBound( arrPrinters ) + 1 & vbCrLf
  56. 	' The first argument is the printer name
  57. 	For i = 0 To UBound( arrPrinters )
  58. 		' List printer names in debugging mode
  59. 		strMsg = strMsg & "Printer " _
  60. 		                & Right( "   " & ( i + 1 ), 3 ) _
  61. 		                & Space( 15 ) & ": " _
  62. 		                & Split( arrPrinters(i), "," )(0) & vbCrLf
  63. 		If LCase( Split( arrPrinters(i), "," )(0) ) = LCase( .Item(0) ) Then
  64. 			strNewDev    = arrPrinters(i)
  65. 			intValidArgs = 1
  66. 		End If
  67. 	Next
  68. 	strMsg = strMsg & vbCrLf
  69. 	' Abort if the printer name doesn't match one of the installed printers
  70. 	intBreak = 3
  71. 	If intValidArgs = 0 Then Syntax
  72. 	' Check for /D, /P, /S or /K switch; other switches are invalid; if the
  73. 	'second argument is "Unnamed" (doesn't start with a forward slash) then
  74. 	' it should be the command that is called to handle the printing itself
  75. 	If Left( .Item(1), 1 ) = "/" Then
  76. 		Select Case UCase( Mid( .Item(1), 2, 1 ) )
  77. 			Case "D"
  78. 				intBreak = 4
  79. 				lngDelay = ValidateDelay( .Item(1) )
  80. 			Case "K"
  81. 				intBreak = 5
  82. 				strKeyStroke = ValidateKeyStroke( .Item(1) )
  83. 			Case "P"
  84. 				blnPause = True
  85. 				intValidArgs = 2
  86. 			Case "S"
  87. 				intBreak = 6
  88. 				strScriptName = ValidateScript( .Item(1) )
  89. 			Case Else
  90. 				intBreak = 7
  91. 				Syntax
  92. 		End Select
  93. 	Else
  94. 		strCmdLine = ""
  95. 		For i = 1 To .Count - 1
  96. 			strCmdLine = strCmdLine & " " & .Item(i)
  97. 		Next
  98. 		strCmdLine = Mid( strCmdLine, 2 )
  99. 	End If
  100. 	' Abort on invalid switch
  101. 	intBreak = 8
  102. 	If intValidArgs = 1 Then Syntax
  103. 	' A third argument could be any of the switches,
  104. 	' or the (continuation of the) printing command
  105. 	If .Count > 2 Then
  106. 		If Left( .Item(2), 1 ) = "/" Then
  107. 			Select Case UCase( Mid( .Item(2), 2, 1 ) )
  108. 				Case "D"
  109. 					intBreak = 9
  110. 					lngDelay = ValidateDelay( .Item(2) )
  111. 				Case "K"
  112. 					intBreak = 10
  113. 					strKeyStroke = ValidateKeyStroke( .Item(2) )
  114. 				Case "P"
  115. 					If blnPause Then
  116. 						intBreak = 11
  117. 						Syntax
  118. 					End If
  119. 					blnPause     = True
  120. 					intValidArgs = 3
  121. 				Case "S"
  122. 					intBreak = 12
  123. 					strScriptName = ValidateScript( .Item(2) )
  124. 				Case Else
  125. 					intBreak = 13
  126. 					Syntax
  127. 			End Select
  128. 		Else
  129. 			strCmdLine = ""
  130. 			For i = 2 To .Count - 1
  131. 				strCmdLine = strCmdLine & " " & .Item(i)
  132. 			Next
  133. 			strCmdLine = Mid( strCmdLine, 2 )
  134. 			intValidArgs = 3
  135. 		End If
  136. 		intBreak = 14
  137. 		If intValidArgs = 2 Then Syntax
  138. 	End If
  139. 	' A fourth argument cannot be a switch
  140. 	If .Count > 3 Then
  141. 		If Left( .Item(3), 1 ) = "/" Then
  142. 			intBreak = 14
  143. 			Syntax
  144. 		Else
  145. 			strCmdLine = ""
  146. 			For i = 3 To .Count - 1
  147. 				strCmdLine = strCmdLine & " " & .Item(i)
  148. 			Next
  149. 			strCmdLine = Mid( strCmdLine, 2 )
  150. 			intValidArgs = 4
  151. 		End If
  152. 		' Abort if the fourth argument was a switch
  153. 		intBreak = 15
  154. 		If intValidArgs = 3 Then Syntax
  155. 	End If
  156. End With
  157.  
  158. ' Check the combination of command line arguments
  159. If strCmdLine = "" Then
  160. 	' Don't send keystrokes if no program is specified
  161. 	intBreak = 16
  162. 	If strKeyStroke <> "" Then Syntax
  163. Else
  164. 	' Program name shouldn't start with a forward slash
  165. 	intBreak = 17
  166. 	If Left( strCmdLine, 1 ) = "/" Then Syntax
  167. End If
  168.  
  169. ' Read the current and the new default printer settings from the registry
  170. Set wshShell = CreateObject( "WScript.Shell" )
  171. strOldDev = wshShell.RegRead( strHive & strKeyPath & "Windows\Device" )
  172. strPrnStr = wshShell.RegRead( strHive & strKeyPath & "PrinterPorts\" & strNewDev )
  173. arrDummy  = Split( strPrnStr, "," )
  174. strNewDev = strNewDev & "," & arrDummy(0) & "," & arrDummy(1)
  175. Set wshShell = Nothing
  176.  
  177. ' Format intermediate results to be displayed in debugging mode
  178. strKeyDescr = Replace( strKeyStroke, "+", "Shift+" )
  179. strKeyDescr = Replace( strKeyDescr,  "%", "Alt+" )
  180. strKeyDescr = Replace( strKeyDescr,  "^", "Ctrl+" )
  181. strMsg = strMsg & "Current default printer   : " & strOldDev & vbCrLf
  182. strMsg = strMsg & "Temporary default printer : " & strNewDev & vbCrLf
  183. strMsg = strMsg & "Restore delay             : " & lngDelay / 1000 & " seconds" & vbCrLf
  184. strMsg = strMsg & "Pause before restore      : " & blnPause & vbCrLf
  185. strMsg = strMsg & "Restore script            : " & strScriptName & vbCrLf
  186. strMsg = strMsg & "Keystrokes                : " & strKeyDescr & vbCrLf
  187. strMsg = strMsg & "Print command             : " & strCmdLine & vbCrLf
  188. If blnDebug Then WScript.Echo strMsg
  189.  
  190. If strScriptName <> "" Then
  191. 	' Create a restore script
  192. 	intBreak = 18
  193. 	If Not CreateScript( strScriptName, strOldDev ) Then Syntax
  194. End If
  195. ' Use wshShell object
  196. Set wshShell = CreateObject( "WScript.Shell" )
  197. ' Change the default printer in the registry
  198. wshShell.RegWrite strRegVal, strNewDev, "REG_SZ"
  199. If strCmdLine <> "" Then
  200. 	' Start the specified printing command
  201. 	wshShell.Run strCmdLine, 9, False
  202. 	If strKeyStroke <> "" Then
  203. 		' Wait at least 5 seconds before sending the specified keystrokes
  204. 		WScript.Sleep 5000
  205. 		wshShell.SendKeys strKeyStroke
  206. 	End If
  207. End If
  208. If lngDelay <> 0 Then
  209. 	' Wait as long as specified by the /D switch
  210. 	WScript.Sleep lngDelay
  211. End If
  212. If blnPause Then
  213. 	' Pause until "OK" button is clicked in the confirmation dialog
  214. 	MsgBox "Wait for the print job to finish." & vbCrLf & _
  215. 	       "Then click ""OK"" to restore the default printer", _
  216. 	       vbOKOnly + vbInformation, "Please wait"
  217. End If
  218. If strScriptName = "" Then
  219. 	' Restore the original default printer unless /S switch was used
  220. 	wshShell.RegWrite strRegVal, strOldDev, "REG_SZ"
  221. Else
  222. 	' Display the command to restore the default printer if /S switch was used
  223. 	WScript.Echo "Use the following command to restore the default printer:" & vbCrLf _
  224. 	           & "CSCRIPT  //NoLogo  """ & strScriptName & """" & vbCrLf
  225. End If
  226. ' Done
  227. Set wshShell = Nothing
  228.  
  229.  
  230. ' Create a script to restore the default printer
  231. Function CreateScript( myScript, myDefPrn )
  232. 	Dim objFSO, objScriptFile
  233. 	Const ForWriting    = 2
  234. 	Const TristateFalse = 0
  235. 	CreateScript = True
  236. 	Set objFSO = CreateObject( "Scripting.FileSystemObject" )
  237. 	On Error Resume Next
  238. 	Set objScriptFile = objFSO.OpenTextFile( myScript, ForWriting, True, TristateFalse )
  239. 	If Err Then CreateScript = False
  240. 	objScriptFile.WriteLine "Set wshShell = CreateObject( ""WScript.Shell"" )"
  241. 	If Err Then CreateScript = False
  242. 	objScriptFile.WriteLine "wshShell.RegWrite """ & strRegVal & """, """ & myDefPrn & """, ""REG_SZ"""
  243. 	If Err Then CreateScript = False
  244. 	objScriptFile.WriteLine "Set wshShell = Nothing"
  245. 	If Err Then CreateScript = False
  246. 	On Error Goto 0
  247. 	Set objScriptFile = Nothing
  248. 	Set objFSO        = Nothing
  249. End Function
  250.  
  251.  
  252. ' Display a help message
  253. Sub Syntax( )
  254. 	If blnDebug Then
  255. 		strMsg = strMsg & "Breakpoint " & intBreak & vbCrLf & vbCrLf
  256. 	Else
  257. 		strMsg = ""
  258. 	End If
  259. 	strMsg = strMsg _
  260. 	       & "Print2.vbs,  Version 1.00 for Windows 2000 and later" _
  261. 	       & vbCrLf _
  262. 	       & "Temporarily swap the default printer for programs that only support printing" _
  263. 	       & vbCrLf _
  264. 	       & "to the default printer (""Print""), not to other printers (""PrintTo"")." _
  265. 	       & vbCrLf & vbCrLf _
  266. 	       & "Usage:   PRINT2.VBS  printer  [ options ]  [ printprog  [ printprogargs ]]" _
  267. 	       & vbCrLf & vbCrLf _
  268. 	       & "Where:   printer  is the name of the temporary default printer" _
  269. 	       & vbCrLf _
  270. 	       & "         options  can be a combination of these switches:" _
  271. 	       & vbCrLf _
  272. 	       & "                  [ /D:seconds | /P | /S:scriptname ] [ /K:keystroke ]" _
  273. 	       & vbCrLf _
  274. 	       & "                  /D   restore default printer after specified delay in seconds" _
  275. 	       & vbCrLf _
  276. 	       & "                  /P   wait for confirmation to restore the default printer" _
  277. 	       & vbCrLf _
  278. 	       & "                  /S   create a script that will restore the default printer" _
  279. 	       & vbCrLf _
  280. 	       & "                  /K   send keystroke to printprog after 5 seconds" _
  281. 	       & vbCrLf _
  282. 	       & "                       (use VBScript's SendKeys( ) syntax for keystroke)" _
  283. 	       & vbCrLf _
  284. 	       & "         printprog  [ printprogargs ]  optional command to print a file;" _
  285. 	       & vbCrLf _
  286. 	       & "                                       if not specified, /D or /P or /S" _
  287. 	       & vbCrLf _
  288. 	       & "                                       is required and /K is not allowed" _
  289. 	       & vbCrLf & vbCrLf _
  290. 	       & "Example: Print ""test.xps"" on ""HP LaserJet"" using Microsoft's XPS Viewer" _
  291. 	       & vbCrLf _
  292. 	       & "         PRINT2.VBS ""HP LaserJet"" /D:10 /K:""{ENTER}"" XpsRchVw.exe test.xps /P" _
  293. 	       & vbCrLf & vbCrLf _
  294. 	       & "Written by Rob van der Woude" _
  295. 	       & vbCrLf _
  296. 	       & "http://www.robvanderwoude.com"
  297. 	WScript.Echo strMsg
  298. 	WScript.Quit 1
  299. End Sub
  300.  
  301.  
  302. ' Validate the specified delay
  303. Function ValidateDelay( myArgStr )
  304. 	ValidateDelay = 0
  305. 	' Check if mutually exclusive or repeated arguments were used
  306. 	If lngDelay > 0 Or blnPause Or strScriptName <> "" Then
  307. 		Syntax
  308. 	Else
  309. 		lngDelay      = Mid( myArgStr, 4 )
  310. 		If IsNumeric( lngDelay ) Then
  311. 			lngDelay = CLng( 1000 * lngDelay )
  312. 			intValidArgs  = intValidArgs + 1
  313. 		Else
  314. 			Syntax
  315. 		End If
  316. 		ValidateDelay = lngDelay
  317. 	End If
  318. End Function
  319.  
  320.  
  321. ' Validate /K (keystroke) argument
  322. Function ValidateKeyStroke( myArgStr )
  323. 	ValidateKeyStroke = ""
  324. 	' Check if repeated arguments were used
  325. 	If strKeyStroke <> "" Then Syntax
  326. 	If Trim( Mid( myArgStr, 4 ) ) = "" Then
  327. 		Syntax
  328. 	Else
  329. 		ValidateKeyStroke = Mid( myArgStr, 4 )
  330. 		intValidArgs = intValidArgs + 1
  331. 	End if
  332. End Function
  333.  
  334.  
  335. ' Validate the specified restore script path and check if it can be created
  336. Function ValidateScript( myArgStr )
  337. 	Dim blnErr, intPos, objFSO, objScript, strFolder, strScript
  338. 	ValidateScript = ""
  339. 	' Check if mutually exclusive or repeated arguments were used
  340. 	If lngDelay > 0 Or blnPause Or strScriptName <> "" Then Syntax
  341.  
  342. 	blnErr = False
  343.  
  344. 	Set objFSO = CreateObject( "Scripting.FileSystemObject" )
  345. 	strScript = Mid( myArgStr, 4 )
  346.  
  347. 	' Check if parent folder exists
  348. 	If InStr( strScript, "\" ) Then
  349. 		intPos    = InStrRev( strScript, "\" )
  350. 		strFolder = Left( strScript, intPos - 1 )
  351. 		If Not objFSO.FolderExists( strFolder ) Then blnErr = True
  352. 	End If
  353.  
  354. 	' Check if file can be created
  355. 	On Error Resume Next
  356. 	Set objScript = objFSO.CreateTextFile( strScript, True, False )
  357. 	If Err Then blnErr = True
  358. 	objScript.Close
  359. 	Set objScript = Nothing
  360. 	On Error Goto 0
  361.  
  362. 	' Close object and return result
  363. 	Set objFSO = Nothing
  364. 	If blnErr Then
  365. 		Syntax
  366. 	Else
  367. 		intValidArgs   = intValidArgs + 1
  368. 		ValidateScript = strScript
  369. 	End If
  370. End Function
  371.  

page last uploaded: 2017-08-21, 14:26