├── PDFXCview.exe ├── PDFtoPrinter.au3 ├── PDFtoPrinter.exe ├── PDFtoPrinterWinSeven.exe ├── README.md ├── Settings.dat ├── msvcp140.dll ├── msvcp140_1.dll ├── msvcp140_2.dll ├── msvcp140_atomic_wait.dll ├── msvcp140_codecvt_ids.dll ├── pdftoprinter.ico ├── qpdf29.dll └── resource.dat /PDFXCview.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emendelson/pdftoprinter/2fa5d5d0dfc7b0c4db5163529de6b3f93d56ea25/PDFXCview.exe -------------------------------------------------------------------------------- /PDFtoPrinter.au3: -------------------------------------------------------------------------------- 1 | #Region ;**** Directives created by AutoIt3Wrapper_GUI **** 2 | #AutoIt3Wrapper_Icon=pdftoprinter.ico 3 | #AutoIt3Wrapper_Outfile=PDFtoPrinter.exe 4 | #AutoIt3Wrapper_Res_Description=PDFtoPrinter.exe 5 | #AutoIt3Wrapper_Res_Fileversion=2.0.3.220 6 | #AutoIt3Wrapper_Res_Fileversion_AutoIncrement=y 7 | #AutoIt3Wrapper_Res_ProductName=PDFtoPrinter.exe 8 | #AutoIt3Wrapper_Res_SaveSource=y 9 | #AutoIt3Wrapper_Res_Language=1033 10 | #AutoIt3Wrapper_Res_requestedExecutionLevel=asInvoker 11 | #AutoIt3Wrapper_Run_After=d:\dropbox\signfilesem.exe "%out%" 12 | #AutoIt3Wrapper_Run_Tidy=y 13 | #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | Global $msgTitle = "PDFtoPrinter.exe" 27 | Global $specified = 0 28 | Global $cli = 0 29 | Global $debug = 0 30 | Global $printername 31 | Global $defaultprinter 32 | Global $gh 33 | Global $code 34 | Global $silent = 0 ; Do not popup error or warning or password window. 35 | 36 | Local $pth = @WorkingDir 37 | If StringRight($pth, 1) = "\" Then $pth = StringTrimRight($pth, 1) ;Working directory is disk root, C:\ 38 | Local $fn = @ScriptName 39 | Local $noprinter = 0 40 | Local $space = " " 41 | Local $qt = Chr(34) 42 | Local $pdffile = "" 43 | Local $showselptr = 0 44 | Local $pgvar = " " 45 | Local $copies = 1 46 | Local $focus = "" 47 | Local $printstring 48 | Local $recurLevel = 1 ;Recur all files matching filename in this folder. 49 | Local $password = "" 50 | Local $csv = 0 ; Change to 1 to output csv. 51 | Local $mock = 0 ; Really print or just simulate. 52 | Local $pageselector = 0 ; no page selector 53 | Local $pdfgiven = 0 ; What if a printfile name ends with .pdf? deal with it. 54 | Local $printervalid = 1 55 | Local $pageselector = "" 56 | Local $aMultiFiles[0] 57 | Local $morethanone = 0 58 | ;;;; new - disables qpdf 59 | Local $qpdf = 0 60 | 61 | Opt("WinTitleMatchMode", -2) 62 | 63 | Global $OSBuild = 1 64 | $OSBuild = FileGetVersion("user32.dll") 65 | If (StringRegExp($OSBuild, "^(.*)\.(.+)\.(.+)\.(.*)$")) Then 66 | $OSBuild = StringRegExp($OSBuild, "^(.*)\.(.+)\.(.+)\.(.*)$", 1) 67 | $OSBuild = $OSBuild[2] 68 | Else 69 | $OSBuild = @OSBuild 70 | EndIf 71 | If $OSBuild < 10000 Then 72 | Display("Windows 10, Windows Server 2016, or later required.") 73 | $code = 1 74 | Exit $code 75 | EndIf 76 | 77 | If Not ExecutableNameFlag("m") Then 78 | Handle_MultipleInstance() 79 | EndIf 80 | 81 | If ExecutableNameFlag("select") Then $showselptr = 1 ;Printer selection GUI popup 82 | If ExecutableNameFlag("debug") Then $debug = 1 83 | If ExecutableNameFlag("cli") Then $cli = 1 ;Commandline interface only, no gui window 84 | 85 | Local $cmln = $CmdLine[0] ;Total commandline parameters entered. 86 | If $cmln = 0 Then ;If no paramters given 87 | Display("Usage:" & @CRLF & @CRLF _ 88 | & "PDFtoPrinter.exe [path\]filename.pdf [other filenames] [" & $qt & "printer name" & _ 89 | $qt & "] [pages=#-#] [copies=#] [focus=" & $qt & "Window title" & $qt & "] [/debug] [/r] [/R[x]] [/s] [/p:password] [/csv] [/mock]" _ 90 | & @CRLF & @CRLF & "Use quotation marks around [path\]filename with spaces. " _ 91 | & "Relative paths and filename-wildcards (* and ?) are OK." _ 92 | & @CRLF & @CRLF & "If more than one filename, do not use wildcard or /r or /R (recursive option). " _ 93 | & @CRLF & "Default printer is used unless printer name is specified." _ 94 | & @CRLF & @CRLF & "Rename to PDFtoPrinterSelect.exe for select-printer menu." _ 95 | & @CRLF & "(menu does not appear if printer name is specified)." _ 96 | & @CRLF & @CRLF & "Page-range examples: 3 [or] 2-4,6,8-9 [or] " _ 97 | & "8- [or] z-1 for reverse-print [or] z-1:odd|even reverse-print odd/even pages [or] " _ 98 | & "r5-r2 for 5th-to-last to 2nd-to-last page." _ 99 | & @CRLF & @CRLF & "focus= Restores focus to specified window title." _ 100 | & @CRLF & @CRLF & "/mydir= Specific temp folder; use quote marks for path " _ 101 | & "with spaces (default is in user's temp folder)." _ 102 | & @CRLF & @CRLF & "/r Recursive directory listing (this folder only, " _ 103 | & "default when filename includes wildcard)." _ 104 | & @CRLF & @CRLF & "/s Run silently; disable user interaction and focus=" _ 105 | & @CRLF & @CRLF & "/csv Generate csv file listing file(s) printed. " _ 106 | & "CSV file written to %temp%\PDFPrinterTmp." _ 107 | & @CRLF & @CRLF & "/mock Generate csv file only; don't print PDF files." _ 108 | & @CRLF & @CRLF & "/Rn Recursive directory listing to n depth of subfolders; " _ 109 | & "if n is absent, recurs through all subfolders." _ 110 | & @CRLF & @CRLF & "/p:password Password for encrypted pdf." _ 111 | & @CRLF & @CRLF & "/debug Copies print command to Windows clipboard.") 112 | $code = 2 113 | Exit $code 114 | EndIf 115 | 116 | 117 | ;/r recursive this folder 118 | ;/Rn recursive directory listing this folder and sub folders to depth n 119 | ;/p pdf password 120 | ;/verbose not implemented 121 | ;/csv output csv 122 | ;/s(password) if no password or password is wrong or pdf corrupt or invalid pdf no warning gui popup, but log it. 123 | ;/mock generate csv, not real print command is run. 124 | 125 | 126 | ;If printer does not exist in this machine 127 | $printerlist = GetPrinter("", 1) 128 | If UBound($printerlist) = 0 And $mock = 0 Then 129 | Display("No printer found.") 130 | $code = 3 131 | Exit $code 132 | EndIf 133 | 134 | ; default myDir; change via command-line 135 | Local $myDir = @TempDir & "\PDFPrinterTmp" 136 | 137 | ; Parse command-line parameters. 138 | If $cmln >= 1 Then 139 | For $x = 1 To $CmdLine[0] 140 | If StringLower(StringRight($CmdLine[$x], 4)) = ".pdf" Then 141 | ; If first parameter ends with .pdf: If printer name also ends with .pdf, pdf filename should appear before printer name. 142 | If $pdfgiven = 0 Then 143 | $pdfgiven = 1 144 | $pdffile = $CmdLine[$x] 145 | $pdffile = _PathFull($pdffile) 146 | _ArrayAdd($aMultiFiles, $pdffile) 147 | Else 148 | $morethanone = 1 149 | $pdffile = $CmdLine[$x] 150 | $pdffile = _PathFull($pdffile) 151 | _ArrayAdd($aMultiFiles, $pdffile) 152 | EndIf 153 | ElseIf StringLower(StringLeft($CmdLine[$x], 6)) = "pages=" Then 154 | $pageselector = $cmdline[$x] 155 | ElseIf StringLower(StringLeft($CmdLine[$x], 7)) = "copies=" Then ; per Peter Mickle 156 | $copies = (StringMid($CmdLine[$x], 8, -1)) 157 | If Not @Compiled Then ConsoleWrite("Copies: " & $copies & @LF) 158 | If Not StringIsInt($copies) Then 159 | Display("The copies= parameter must use an integer.") 160 | $code = 4 161 | Exit $code 162 | EndIf 163 | $copies = Abs($copies) ; negative integer is interger too. 164 | ElseIf StringLower(StringLeft($CmdLine[$x], 6)) = "focus=" Then ; return Focus 165 | $focus = (StringMid($CmdLine[$x], 7, -1)) 166 | If Not StringLeft($focus, 1) = Chr(34) Then $focus = Chr(34) & $focus 167 | If Not StringRight($focus, 1) = Chr(34) Then $focus = $focus & Chr(34) 168 | If Not @Compiled Then ConsoleWrite("$focus = " & $focus & @LF) 169 | ElseIf StringLower(StringLeft($CmdLine[$x], 7)) = "/mydir=" Then ; return myDir 170 | $myDir = (StringMid($CmdLine[$x], 8, -1)) 171 | ;If Not StringLeft($myDir, 1) = Chr(34) Then $myDir = Chr(34) & $myDir 172 | ;If Not StringRight($myDir, 1) = Chr(34) Then $myDir = $myDir & Chr(34) 173 | If Not @Compiled Then ConsoleWrite("$mydir = " & $myDir & @LF) 174 | ElseIf $CmdLine[$x] = "/debug" Then 175 | $debug = 1 176 | ElseIf StringCompare($CmdLine[$x], "/r", 1) = 0 Then 177 | $recurLevel = 1 178 | ElseIf StringCompare(StringLeft($CmdLine[$x], 2), "/R", 1) = 0 Then 179 | If $CmdLine[$x] = "/R" Then 180 | $recurLevel = 0 ; recursive directory listing to unlimited depth 181 | Else 182 | If StringIsInt(StringTrimLeft($CmdLine[$x], 2)) Then 183 | $recurLevel = 0 - Abs(StringTrimLeft($CmdLine[$x], 2)) 184 | Else 185 | Display("For /Rx x must be number.") 186 | $code = 5 187 | Exit $code 188 | EndIf 189 | EndIf 190 | ElseIf StringLower(StringLeft($CmdLine[$x], 3)) = "/p:" Then 191 | $password = StringTrimLeft($cmdline[$x], 3) 192 | ElseIf StringLower(StringLeft($CmdLine[$x], 4)) = "/csv" Then 193 | $csv = 1 194 | ElseIf StringLower(StringLeft($CmdLine[$x], 2)) = "/s" Then 195 | $silent = 1 196 | ElseIf StringLower(StringLeft($CmdLine[$x], 5)) = "/mock" Then 197 | $mock = 1 198 | Else 199 | $printervalid = 0 200 | $printername = $CmdLine[$x] 201 | For $i = 0 To UBound($printerlist) - 1 202 | If $printerlist[$i] = $CmdLine[$x] Then 203 | $specified = 1 204 | $showselptr = 0 205 | $printervalid = 1 206 | ExitLoop 207 | EndIf 208 | Next 209 | If StringLeft($printername, 2) = "\\" Then 210 | $printervalid = 1 211 | EndIf 212 | EndIf 213 | Next 214 | EndIf 215 | 216 | ; if no printer or invalid parameters encountered: 217 | If $printervalid = 0 Then 218 | Display("Printer name """ & $printername & """ not found or argument """ & $printername & """is not valid.") 219 | $code = 6 220 | Exit $code 221 | EndIf 222 | 223 | ; if no pdf file name given: 224 | If $pdffile = "" Then 225 | Display("Wrong arguments: no [path]filename with .pdf extension provided.") 226 | $code = 7 227 | Exit $code 228 | EndIf 229 | 230 | ; get pdf file list 231 | If $recurLevel <= 1 Then 232 | $pdffiles = getfilematched($pdffile, $recurLevel, $pth) 233 | If @error Then 234 | Display($pdffiles) 235 | $code = 8 236 | Exit $code 237 | EndIf 238 | Else 239 | Local $pdffiles[2] 240 | $pdffiles[0] = 1 241 | $pdffiles[1] = $pdffile 242 | EndIf 243 | 244 | ; if PDFXchange Viewer settings available in working directory or script directory, use it. 245 | ; PDF-Xchange Viewer Settings.dat in working directory has higher priority. 246 | Local $custom = 0 247 | If FileExists($pth & "\PDF-Xchange Viewer Settings.dat") Then $custom = 2 248 | If FileExists(@ScriptDir & "\PDF-Xchange Viewer Settings.dat") Then $custom = 1 249 | 250 | ; extract PDFXChange Viewer and settings.dat and qpdf29.dll ... to %temp% directory. 251 | ;Local $myDir = @TempDir & "\PDFPrinterTmp" 252 | DirCreate($myDir) 253 | $tmp = FileInstall(".\PDFXCview.exe", $myDir & "\PDFXCview.exe") 254 | FileInstall(".\msvcp140.dll", $myDir & "\msvcp140.dll") 255 | FileInstall(".\msvcp140_1.dll", $myDir & "\msvcp140_1.dll") 256 | FileInstall(".\msvcp140_2.dll", $myDir & "\msvcp140_2.dll") 257 | FileInstall(".\msvcp140_atomic_wait.dll", $myDir & "\msvcp140_atomic_wait.dll") 258 | FileInstall(".\msvcp140_codecvt_ids.dll", $myDir & "\msvcp140_codecvt_ids.dll") 259 | FileInstall(".\qpdf29.dll", $myDir & "\qpdf29.dll") 260 | FileInstall(".\resource.dat", $myDir & "\resource.dat", 1) 261 | FileDelete($myDir & "\settings.dat") 262 | 263 | ; next lines fixed by Wilberto Morales 264 | If $custom = 1 Then 265 | FileCopy(@ScriptDir & "\PDF-Xchange Viewer Settings.dat", $myDir & "\settings.dat", 1) 266 | ElseIf $custom = 2 Then 267 | FileCopy($pth & "\PDF-Xchange Viewer Settings.dat", $myDir & "\settings.dat", 1) 268 | Else 269 | FileInstall(".\Settings.dat", $myDir & "\settings.dat", 1) 270 | EndIf 271 | 272 | $errors = "" ; variable to collect error information. 273 | 274 | Local $summary[1][12] ; array variable to collect information for CSV. 275 | 276 | ; csv file title 277 | $tmpstr = "Index, Filepath, Filename, Datetime, IsEntrypted, PageCount, Command string executed(can be used for bat), Page selector, Total pages selected, Copies,Result(assume all actions reqiuring human interaction is successful even you cancelled the password input window.), Error info" 278 | 279 | _ArrayInsert($summary, 0, $tmpstr, 0, ",") 280 | 281 | ; if more than one file specified on the command line, then use those files as the pdf file list 282 | If $morethanone = 1 Then 283 | $fileCount = UBound($aMultiFiles) 284 | _ArrayInsert($aMultiFiles, 0, $fileCount) 285 | $pdffiles = $aMultiFiles 286 | EndIf 287 | ; _ArrayDisplay($pdffiles) 288 | ; _ArrayDisplay($aMultiFiles) 289 | ; Exit 290 | 291 | ; loop all matching pdf files 292 | For $i = 1 To $pdffiles[0] 293 | $encrypted = 0 ; 294 | $tmpstr = "" 295 | $tmpstr0 = $i & @CRLF & StringMid($pdffiles[$i], 1, StringInStr($pdffiles[$i], "\", 0, -1)) & @CRLF & StringTrimLeft($pdffiles[$i], StringInStr($pdffiles[$i], "\", 0, -1)) & @CRLF 296 | 297 | If Not FileExists($pdffiles[$i]) Then 298 | If $cli = 0 Then 299 | If $silent = 0 Then MsgBox(0, $msgTitle, $pdffiles[$i] & " - File not found.", 3) 300 | Else 301 | ConsoleWrite($pdffile[$i] & " - File not found.") 302 | EndIf 303 | $errors = @CRLF & $errors & @CRLF & $pdffiles[$i] & " : file not found." 304 | $tmpstr = $tmpstr0 & _Now() & @CRLF & @CRLF & @CRLF & @CRLF & @CRLF & @CRLF & $copies & @CRLF & "Fail" & @CRLF & "File not found." 305 | _ArrayInsert($summary, $i, $tmpstr, 0, @CRLF, @TAB) 306 | ContinueLoop ;loop next pdf file. 307 | EndIf 308 | 309 | ;;; new - disables qpdf 310 | ;; If $pageselector <> "" Then $qpdf = 1 311 | ;;; new - 0 disables qpdf 312 | $qpdf = 1 313 | 314 | If $qpdf = 1 Then 315 | ; get page count of pdf file. If qpdf29.dll does not exist in %temp%\pdftoprintertmp, try to load qpdf29.dll in the script folder. 316 | $pdfpagecount = qpdfgetpagecount($pdffiles[$i], $password, $myDir & "\qpdf29.dll") 317 | If @error Then ; error getting pdf page count, means pdf is invalid or corrupted. 318 | ; pdf viewer may able to repair some corrupted pdf file, no chance to do so now. 319 | ; qpdf can get pagecount of encrypted pdf without password, so error is not set when pdf is encrypted. 320 | If $cli = 0 Then 321 | If $silent = 0 Then MsgBox(0, $msgTitle, $pdfpagecount, 3) 322 | Else 323 | ConsoleWrite($pdfpagecount) 324 | EndIf 325 | $errors = @CRLF & $errors & @CRLF & $pdffiles[$i] & " : " & _ 326 | "You should install the latest VC redistributable from Microsoft." & @CRLF & @CRLF & _ 327 | "See the download page for PDFtoPrinter." 328 | $tmpstr = $tmpstr0 & _Now() & @CRLF & @CRLF & @CRLF & @CRLF & $pageselector & @CRLF & @CRLF & $copies & @CRLF & "Fail" & @CRLF & "getPageCount() error, pdf maybe invalid or corrupted." 329 | _ArrayInsert($summary, $i, $tmpstr, 0, @CRLF, @TAB) 330 | ContinueLoop ;loop next pdf file. 331 | EndIf 332 | 333 | ;if pdfpagecount is less than 0, denote pdf is encrypted. 334 | If $pdfpagecount < 0 Then $encrypted = 1 335 | $pdfpagecount = Abs($pdfpagecount) 336 | 337 | ;if pageseletor is not provided, all pages will be printed. 338 | If $pageselector <> "" Then 339 | Local $pageselectortmp = parsepage($pageselector, $pdfpagecount) 340 | If @error Then 341 | If $cli = 0 Then 342 | If $silent = 0 Then MsgBox(0, $msgTitle, $pageselectortmp, 3) 343 | Else 344 | ConsoleWrite($pageselectortmp) 345 | EndIf 346 | $errors = @CRLF & $errors & @CRLF & $pdffiles[$i] & " : Page selector """ & $pageselector & """ error(not valid)." 347 | $tmpstr = $tmpstr0 & _Now() & @CRLF & $encrypted & @CRLF & $pdfpagecount & @CRLF & @CRLF & $pageselector & @CRLF & @CRLF & $copies & @CRLF & "Fail" & @CRLF & "Invalid page selector: " & $pageselectortmp 348 | _ArrayInsert($summary, $i, $tmpstr, 0, @CRLF, @TAB) 349 | ContinueLoop ;loop next pdf file. 350 | EndIf 351 | Else 352 | Local $pageselectortmp[2] = [$pdfpagecount, ""] 353 | EndIf 354 | 355 | $pgvar = "&" & $pageselectortmp[1] & $qt & " " ;/Pages= variable 356 | If Not @Compiled Then ConsoleWrite("Pages: " & $pgvar & @LF) 357 | 358 | If $pgvar = " " Then $pgvar = $qt 359 | 360 | EndIf 361 | 362 | If $specified = 1 Then ; printer name specified in command line parameters. 363 | ; $printstring = " /print:printer=" & $qt & $printername & $qt & $pgvar ; fixed per Peter Mickle 364 | $printstring = " " & $qt & "/printto:" & $pgvar & $qt & $printername & $qt 365 | 366 | For $j = 1 To $copies 367 | ;msgbox(0,"",$qt & $myDir & "\PDFXCview.exe" & $qt & $printstring & " " & $qt & $pdffiles[$i] & $qt) 368 | If Not @Compiled Then ConsoleWrite("specified: " & @LF & $qt & $myDir & "\PDFXCview.exe" & $qt & $printstring & _ 369 | " " & $qt & $pdffiles[$i] & $qt & @LF) 370 | If $mock <> 1 Then RunWait($qt & $myDir & "\PDFXCview.exe" & $qt & " /importp settings.dat", $myDir, @SW_SHOW) 371 | 372 | If $encrypted Then 373 | If $cli Then 374 | $errors = @CRLF & $errors & @CRLF & $pdffiles[$i] & " : This file is password protected, no way to enter password in commandline." 375 | $tmpstr = $tmpstr0 & _Now() & @CRLF & $encrypted & @CRLF & $pdfpagecount & @CRLF & @CRLF & $pageselector & @CRLF & $pageselectortmp[0] & @CRLF & $copies & @CRLF & "Fail" & @CRLF & "This file is password protected, no way to enter password in commandline." 376 | _ArrayInsert($summary, $i, $tmpstr, 0, @CRLF, @TAB) 377 | ContinueLoop 2 378 | EndIf 379 | If $password = "" Then 380 | $errors = @CRLF & $errors & @CRLF & $pdffiles[$i] & " : This file is password protected, but password is not provided by /p:password." 381 | $tmpstr = $tmpstr0 & _Now() & @CRLF & $encrypted & @CRLF & $pdfpagecount & @CRLF & @CRLF & $pageselector & @CRLF & $pageselectortmp[0] & @CRLF & $copies & @CRLF & "Fail" & @CRLF & "his file is password protected, but password is not provided by /p:password." 382 | _ArrayInsert($summary, $i, $tmpstr, 0, @CRLF, @TAB) 383 | ContinueLoop 2 384 | Else ;if pdf encryped and password given. 385 | $cmdstr = $qt & $myDir & "\PDFXCview.exe" & $qt & $printstring & " " & $qt & $pdffiles[$i] & $qt 386 | If $mock <> 1 Then 387 | $pid = Run($qt & $myDir & "\PDFXCview.exe" & $qt & $printstring & _ 388 | " " & $qt & $pdffiles[$i] & $qt, $myDir, @SW_SHOW) ;run pdfxcview to print pdf. 389 | 390 | $ireslt = sendpassword($password) ;send password to password input window. 391 | 392 | If $ireslt Then ;if password is wrong 393 | If $silent Then 394 | $errors = @CRLF & $errors & @CRLF & $pdffiles[$i] & " : This file is password protected, but password is wrong." 395 | $tmpstr = $tmpstr0 & _Now() & @CRLF & $encrypted & @CRLF & $pdfpagecount & @CRLF & @CRLF & $pageselector & @CRLF & $pageselectortmp[0] & @CRLF & $copies & @CRLF & "Fail" & @CRLF & "This file is password protected, but password is wrong" 396 | _ArrayInsert($summary, $i, $tmpstr, 0, @CRLF, @TAB) 397 | ProcessClose($pid) ;force pdfxcview.exe to close 398 | Else ;open a dialog for entering password 399 | ProcessWaitClose($pid, 120) ;dialog box closes after two minutes; what happens next? 400 | EndIf 401 | EndIf 402 | EndIf 403 | EndIf 404 | Else ;pdf not encrypted. 405 | ;Will any other warning or error windows pop up? I don't know, otherwise I should force close pdfxcview when silent=1. 406 | $cmdstr = $qt & $myDir & "\PDFXCview.exe" & $qt & $printstring & " " & $qt & $pdffiles[$i] & $qt 407 | If $mock <> 1 Then RunWait($qt & $myDir & "\PDFXCview.exe" & $qt & $printstring & _ 408 | " " & $qt & $pdffiles[$i] & $qt, $myDir, @SW_SHOW) 409 | EndIf 410 | 411 | ; error running pdfxcview.exe 412 | If @error Then 413 | If $cli = 0 Then 414 | If $silent = 0 Then MsgBox(0, $msgTitle, @error & @CRLF & @CRLF & "Could not run PDFXCview.EXE.", 3) 415 | Else 416 | ConsoleWrite(@error & @CRLF & @CRLF & "Could not run PDFXCview.EXE.") 417 | EndIf 418 | $errors = @CRLF & $errors & @CRLF & $pdffiles[$i] & " : Could not run PDFXCview.EXE." 419 | $tmpstr = $tmpstr0 & _Now() & @CRLF & $encrypted & @CRLF & $pdfpagecount & @CRLF & $cmdstr & @CRLF & $pageselector & @CRLF & $pageselectortmp[0] & @CRLF & $copies & @CRLF & "Fail" & @CRLF & "Could not run PDFXCview.EXE" 420 | _ArrayInsert($summary, $i, $tmpstr, 0, @CRLF, @TAB) 421 | ContinueLoop 2 422 | EndIf 423 | Next 424 | 425 | Else ;if printer is not specified in commandline, use default or let user select printer 426 | 427 | If $showselptr = 1 Then 428 | Local $ptrselmsg = "Select a printer for this document:" 429 | $printername = 0 430 | GetPrinter($ptrselmsg) 431 | Do 432 | Sleep(100) 433 | Until $printername 434 | $noprinter = 0 435 | If $printername = "nul" Then 436 | $noprinter = 1 437 | EndIf 438 | $printstring = " " & $qt & "/printto:" & $pgvar & $qt & $printername & $qt ; fix by Mr. Liu 439 | Else 440 | $printstring = " " & $qt & "/print:default=no" & $pgvar ; & $qt 441 | EndIf 442 | 443 | If $noprinter = 0 Then 444 | For $j = 1 To $copies 445 | If $mock <> 1 Then RunWait($qt & $myDir & "\PDFXCview.exe" & $qt & " /importp settings.dat", $myDir, @SW_SHOW) 446 | If $encrypted Then 447 | If $cli Then 448 | $errors = @CRLF & $errors & @CRLF & $pdffiles[$i] & " : This file is password protected, no way to enter in commandline." 449 | $tmpstr = $tmpstr0 & _Now() & @CRLF & $encrypted & @CRLF & $pdfpagecount & @CRLF & @CRLF & $pageselector & @CRLF & $pageselectortmp[0] & @CRLF & $copies & @CRLF & "Fail" & @CRLF & "This file is password protected, no way to enter password in commandline." 450 | _ArrayInsert($summary, $i, $tmpstr, 0, @CRLF, @TAB) 451 | ContinueLoop 2 452 | EndIf 453 | 454 | If $password = "" Then 455 | $errors = @CRLF & $errors & @CRLF & $pdffiles[$i] & " : This file is password protected, but password is not provided by /p:password." 456 | $tmpstr = $tmpstr0 & _Now() & @CRLF & $encrypted & @CRLF & $pdfpagecount & @CRLF & @CRLF & $pageselector & @CRLF & $pageselectortmp[0] & @CRLF & $copies & @CRLF & "Fail" & @CRLF & "This file is password protected, but password is not provided by /p:password." 457 | _ArrayInsert($summary, $i, $tmpstr, 0, @CRLF, @TAB) 458 | ContinueLoop 2 459 | Else 460 | $cmdstr = $qt & $myDir & "\PDFXCview.exe" & $qt & $printstring & " " & $qt & $pdffiles[$i] & $qt 461 | If $mock <> 1 Then 462 | $pid = Run($qt & $myDir & "\PDFXCview.exe" & $qt & $printstring & " " & _ 463 | $qt & $pdffiles[$i] & $qt, $myDir, @SW_SHOW) 464 | $ireslt = sendpassword($password) 465 | If $ireslt Then 466 | If $silent Then ; wrong password 467 | $errors = @CRLF & $errors & @CRLF & $pdffiles[$i] & " : This file is password protected, but password is wrong." 468 | $tmpstr = $tmpstr0 & _Now() & @CRLF & $encrypted & @CRLF & $pdfpagecount & @CRLF & @CRLF & $pageselector & @CRLF & $pageselectortmp[0] & @CRLF & $copies & @CRLF & "Fail" & @CRLF & "This file is password protected, but password is wrong" 469 | _ArrayInsert($summary, $i, $tmpstr, 0, @CRLF, @TAB) 470 | ProcessClose($pid) 471 | Else 472 | ProcessWaitClose($pid, 120) 473 | ; dialog waits two minutes before closing; what happens next? 474 | EndIf 475 | EndIf 476 | EndIf 477 | EndIf 478 | Else 479 | $cmdstr = $qt & $myDir & "\PDFXCview.exe" & $qt & $printstring & " " & $qt & $pdffiles[$i] & $qt 480 | If $mock <> 1 Then RunWait($qt & $myDir & "\PDFXCview.exe" & $qt & $printstring & " " & _ 481 | $qt & $pdffiles[$i] & $qt, $myDir, @SW_SHOW) 482 | EndIf 483 | If @error Then 484 | If $cli = 0 Then 485 | If $silent = 0 Then MsgBox(0, $msgTitle, @error & @CRLF & @CRLF & "Could not run PDFXCview.EXE.", 3) 486 | Else 487 | ConsoleWrite(@error & @CRLF & @CRLF & "Could not run PDFXCview.EXE.") 488 | EndIf 489 | $errors = @CRLF & $errors & @CRLF & $pdffiles[$i] & " : Could not run PDFXCview.EXE." 490 | $tmpstr = $tmpstr0 & _Now() & @CRLF & $encrypted & @CRLF & $pdfpagecount & @CRLF & $cmdstr & @CRLF & $pageselector & @CRLF & $pageselectortmp[0] & @CRLF & $copies & @CRLF & "Fail" & @CRLF & "Could not run PDFXCview.EXE." 491 | _ArrayInsert($summary, $i, $tmpstr, 0, @CRLF, @TAB) 492 | ContinueLoop 2 493 | EndIf 494 | Next 495 | Else ; no printer selected 496 | If $mock <> 1 Then 497 | $errors = @CRLF & $errors & @CRLF & $pdffiles[$i] & " : You did not select a printer." 498 | $tmpstr = $tmpstr0 & _Now() & @CRLF & $encrypted & @CRLF & $pdfpagecount & @CRLF & $cmdstr & @CRLF & $pageselector & @CRLF & $pageselectortmp[0] & @CRLF & $copies & @CRLF & "Fail" & @CRLF & ": You had choice, but no printer is selected." 499 | _ArrayInsert($summary, $i, $tmpstr, 0, @CRLF, @TAB) 500 | ContinueLoop 501 | EndIf 502 | EndIf 503 | 504 | EndIf 505 | If UBound($summary) = $i + 1 Then ; no error occured earlier; otherwise loop is skipped. 506 | $tmpstr = $tmpstr0 & _Now() & @CRLF & $encrypted & @CRLF & $pdfpagecount & @CRLF & $cmdstr & @CRLF & $pageselector & @CRLF & $pageselectortmp[0] & @CRLF & $copies & @CRLF & "Success" & @CRLF 507 | _ArrayInsert($summary, $i, $tmpstr, 0, @CRLF, @TAB) 508 | EndIf 509 | 510 | ; script name has string "debug". 511 | If $debug = 1 Then 512 | ClipPut($qt & $myDir & "\PDFXCview.exe" & $qt & $printstring & _ 513 | " " & $qt & $pdffiles[$i] & $qt) 514 | Display("The PDFXCview.exe print command has been copied to the clipboard. " & _ 515 | "In case of problems, open a command window, paste in the command, and experiment with it.") 516 | EndIf 517 | If $focus <> "" And $silent <> 0 Then WinActivate($focus) 518 | Next 519 | 520 | If $errors <> "" Then 521 | If $cli = 0 Then 522 | If $silent = 0 Then MsgBox(0, "Error lists:", $errors) 523 | EndIf 524 | ConsoleWrite("Error lists: " & @CRLF & $errors) 525 | $code = 9 526 | Else 527 | $code = 0 528 | EndIf 529 | 530 | ;write csv file 531 | If $csv = 1 Or $mock = 1 Then 532 | Local $output_file = $myDir & "\summary_utf8.csv" 533 | DeleteFile($output_file) 534 | FileWrite($output_file, _ArrayToCSV($summary)) 535 | EndIf 536 | 537 | ; cleanup $mydir? 538 | ;DeleteFile($myDir & "\PDFXCview.exe") 539 | ;DeleteFile($myDir & "\qpdf29.dll") 540 | ;DeleteFile($myDir & "\resource.dat") 541 | ;DeleteFile($myDir & "\settings.dat") 542 | 543 | Exit $code ;main script ends here. 544 | 545 | Func _ArrayToCSV($aArray, $sDelim = Default, $sNewLine = Default, $bFinalBreak = True) 546 | ; #FUNCTION# ==================================================================================================================== 547 | ; Name...........: _ArrayToCSV 548 | ; Description ...: Converts a two dimensional array to CSV format 549 | ; Syntax.........: _ArrayToCSV ( $aArray [, $sDelim [, $sNewLine [, $bFinalBreak ]]] ) 550 | ; Parameters ....: $aArray - The array to convert 551 | ; $sDelim - Optional - Delimiter set to comma by default (see comments) 552 | ; $sNewLine - Optional - New Line set to @LF by default (see comments) 553 | ; $bFinalBreak - Set to true in accordance with common practice => CSV Line termination 554 | ; Return values .: Success - Returns a string in CSV format 555 | ; Failure - Sets @error to: 556 | ; |@error = 1 - First parameter is not a valid array 557 | ; |@error = 2 - Second parameter is not a valid string 558 | ; |@error = 3 - Third parameter is not a valid string 559 | ; |@error = 4 - 2nd and 3rd parameters must be different characters 560 | ; Author ........: czardas 561 | ; Comments ......; One dimensional arrays are returned as multiline text (without delimiters) 562 | ; ; Some users may need to set the second parameter to semicolon to return the prefered CSV format 563 | ; ; To convert to TSV use @TAB for the second parameter 564 | ; ; Some users may wish to set the third parameter to @CRLF 565 | ; =============================================================================================================================== 566 | If Not IsArray($aArray) Or UBound($aArray, 0) > 2 Or UBound($aArray) = 0 Then Return SetError(1, 0, "") 567 | If $sDelim = Default Then $sDelim = "," 568 | If $sDelim = "" Then Return SetError(2, 0, "") 569 | If $sNewLine = Default Then $sNewLine = @LF 570 | If $sNewLine = "" Then Return SetError(3, 0, "") 571 | If $sDelim = $sNewLine Then Return SetError(4, 0, "") 572 | 573 | Local $iRows = UBound($aArray), $sString = "" 574 | If UBound($aArray, 0) = 2 Then ; Check if the array has two dimensions 575 | Local $iCols = UBound($aArray, 2) 576 | For $i = 0 To $iRows - 1 577 | For $j = 0 To $iCols - 1 578 | If StringRegExp($aArray[$i][$j], '["\r\n' & $sDelim & ']') Then 579 | $aArray[$i][$j] = '"' & StringReplace($aArray[$i][$j], '"', '""') & '"' 580 | EndIf 581 | $sString &= $aArray[$i][$j] & $sDelim 582 | Next 583 | $sString = StringTrimRight($sString, StringLen($sDelim)) & $sNewLine 584 | Next 585 | Else ; The delimiter is not needed 586 | For $i = 0 To $iRows - 1 587 | If StringRegExp($aArray[$i], '["\r\n' & $sDelim & ']') Then 588 | $aArray[$i] = '"' & StringReplace($aArray[$i], '"', '""') & '"' 589 | EndIf 590 | $sString &= $aArray[$i] & $sNewLine 591 | Next 592 | EndIf 593 | If Not $bFinalBreak Then $sString = StringTrimRight($sString, StringLen($sNewLine)) ; Delete any newline characters added to the end of the string 594 | Return $sString 595 | EndFunc ;==>_ArrayToCSV 596 | 597 | Func DeleteFile($file) ; è unito con _Spediamo_it_CSV() 598 | 599 | $file_usage = FileOpen($file, 1) 600 | 601 | If $file_usage = -1 Then 602 | If $silent = 0 Then MsgBox(0, @ScriptName, $file & " is in use." & @CRLF & _ 603 | 'Please close it before continuing.') 604 | $code = 10 605 | Exit $code 606 | EndIf 607 | 608 | FileClose($file_usage) 609 | 610 | If FileExists($file) Then 611 | FileDelete($file) 612 | EndIf 613 | 614 | EndFunc ;==>DeleteFile 615 | 616 | Func GetPrinter($ptrselmsg, $flag = 0) 617 | ;$ptrselmsg set select printer GUI window title. 618 | ;If flag=1, just get available printer list. No select window popup, return an array containing all printers 619 | ;If flag=0, popup window for user to select printer, selected printer is returned, otherwise "nul" is returned. 620 | Global $printer_list[1] 621 | Global $printer_list_ext[1] 622 | Global $printer_radio_array[1] 623 | $regprinters = "HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Devices" 624 | $currentprinter = RegRead("HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows\", "Device") 625 | $defaultprinter = StringLeft($currentprinter, StringInStr($currentprinter, ",") - 1) 626 | Local $i = 1 ; fix by Mr. Liu 627 | Dim $erreur_reg = False 628 | While Not $erreur_reg 629 | $imprimante = RegEnumVal($regprinters, $i) 630 | $erreur_reg = @error 631 | If Not $erreur_reg Then 632 | _ArrayAdd($printer_list, $imprimante) 633 | _ArrayAdd($printer_list_ext, $imprimante & "," & RegRead($regprinters, $imprimante)) 634 | EndIf 635 | $i = $i + 1 636 | WEnd 637 | _ArrayDelete($printer_list, 0) 638 | _ArrayDelete($printer_list_ext, 0) 639 | If $flag = 1 Then Return $printer_list ;What if no printer added? what error? 640 | ;msgbox(0,"",ubound($printer_list)) 641 | 642 | If UBound($printer_list) >= 2 Then ;; if 2 or more printers available, we show the dialog 643 | Dim $groupheight = (UBound($printer_list) + 1) * 25 ;; 30 644 | Dim $guiheight = $groupheight + 50 645 | Dim $buttontop = $groupheight + 20 646 | Opt("GUIOnEventMode", 1) 647 | $gh = GUICreate($ptrselmsg, 400, $guiheight) 648 | Dim $font = "Verdana" 649 | GUISetFont(10, 400, 0, $font) 650 | GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked") 651 | GUISetFont(10, 400, 0, $font) 652 | GUICtrlCreateGroup("Available printers:", 10, 10, 380, $groupheight) 653 | Dim $position_vertical = 5 ;; 0 654 | For $i = 0 To UBound($printer_list) - 1 Step 1 655 | GUISetFont(10, 400, 0, $font) 656 | $position_vertical = $position_vertical + 25 ;; 30 657 | $radio = GUICtrlCreateRadio($printer_list[$i], 20, $position_vertical, 350, 20) 658 | _ArrayAdd($printer_radio_array, $radio) 659 | If $currentprinter = $printer_list_ext[$i] Then 660 | GUICtrlSetState($radio, $GUI_CHECKED) 661 | EndIf 662 | Next 663 | _ArrayDelete($printer_radio_array, 0) 664 | GUISetFont(10, 400, 0, $font) 665 | $okbutton = GUICtrlCreateButton("OK", 10, $buttontop, 50, 25) 666 | GUICtrlSetOnEvent($okbutton, "OKButton") 667 | Local $AccelKeys[2][2] = [["{ENTER}", $okbutton], ["^O", $okbutton]] 668 | GUISetAccelerators($AccelKeys) 669 | GUISetState() 670 | EndIf 671 | EndFunc ;==>GetPrinter 672 | 673 | Func OKButton() 674 | For $i = 0 To UBound($printer_radio_array) - 1 Step 1 675 | If GUICtrlRead($printer_radio_array[$i]) = 1 Then 676 | $printername = StringLeft($printer_list_ext[$i], StringInStr($printer_list_ext[$i], ",") - 1) 677 | EndIf 678 | Next 679 | GUIDelete($gh) 680 | If Not @Compiled Then ConsoleWrite($printername & @LF) 681 | EndFunc ;==>OKButton 682 | 683 | Func CLOSEClicked() 684 | GUIDelete($gh) 685 | $printername = "nul" 686 | If Not @Compiled Then ConsoleWrite($printername & @LF) 687 | EndFunc ;==>CLOSEClicked 688 | 689 | ;~ Func Cancelled() 690 | ;~ If $cli = 0 Then 691 | ;~ MsgBox(262144, $msgTitle, "Script cancelled.") 692 | ;~ EndIf 693 | ;~ Exit 694 | ;~ EndFunc ;==>Cancelled 695 | 696 | Func _FileIsUsed($sFilePath) ;; By Nessie. Modified by guinness. 697 | Local Const $hFileOpen = _WinAPI_CreateFile($sFilePath, $CREATE_ALWAYS, (DriveGetType($sFilePath)) = 'NETWORK' ? $FILE_SHARE_READ : $FILE_SHARE_WRITE) 698 | Local $fReturn = True 699 | If $hFileOpen Then 700 | _WinAPI_CloseHandle($hFileOpen) 701 | $fReturn = False 702 | EndIf 703 | 704 | If $fReturn Then 705 | $fReturn = _WinAPI_GetLastError() = $ERROR_SHARING_VIOLATION 706 | EndIf 707 | Return $fReturn 708 | EndFunc ;==>_FileIsUsed 709 | 710 | Func Handle_MultipleInstance() 711 | If _Singleton(StringReplace(@ScriptFullPath, '\', '/'), 1) = 0 Then 712 | Flash("PDFtoPrinter.exe is already running. Please wait.") 713 | $code = 11 714 | Exit $code 715 | EndIf 716 | EndFunc ;==>Handle_MultipleInstance 717 | 718 | Func sendpassword($password) 719 | ;send password to pdfxcview.exe input password window. 720 | $hWnd = WinWait("Enter Document Password", "Please enter valid user or owner password", 4) ;wait at most 4 seconds for input password window to popup. 721 | If WinExists($hWnd) Then 722 | ControlSetText("Enter Document Password", "", 1000, $password, 1) 723 | ControlClick("Enter Document Password", "OK", 1) 724 | $hWnd = WinWait("Enter Document Password", "Please enter valid user or owner password", 1) ;wait 1 second to see if password is correct. 725 | If $hWnd <> 0 Then 726 | Return SetError(1, "Wrong password.") 727 | Else 728 | Return 0 729 | EndIf 730 | EndIf 731 | EndFunc ;==>sendpassword 732 | 733 | 734 | 735 | Func parsepage($pagestr, $pagecount = 3000) 736 | ;$pagestr pages=1,2-10:even,11-3,r5-r2,z:odd,-7,8-:even 737 | ;return an array two elements. array[0] is the selected pages count, array[1]is string pages=1,2,4,6,11-3 that pdfxcview can accept. 738 | ;pages=1-4,1-4 will print the document pages 1-4 twice, it's another way to print copies of a pdf of diffrent page ranges. 739 | ;Xchange viewer support page number greater than the actual pagecount, but page number greater than pagecount is not printed(of cource), so default 3000 is added. 740 | Local $outpage = "" 741 | $pages = StringTrimLeft($pagestr, 6) 742 | $pagearray = StringSplit($pages, ",") ;split by comma 743 | $totalpages = 0 744 | For $i = 1 To UBound($pagearray) - 1 745 | $outpagetmp = splitexpand($pagearray[$i], $pagecount) 746 | If @error Then Return SetError(1, 0, "Invalid page selector " & $pagearray[$i] & ". ") ;invalid page selector 747 | If $outpagetmp[1] <> "" Then 748 | $seperator = "," 749 | $outpage = $outpage & $seperator & $outpagetmp[1] 750 | ElseIf $outpagetmp[1] = "" Then 751 | $seperator = "" 752 | EndIf 753 | $totalpages = $totalpages + $outpagetmp[0] 754 | Next 755 | 756 | If $outpage = "" Then 757 | Return SetError(2, 0, "No Page Selected") ;no page selected 758 | Else 759 | Local $finaloutput[2] = [$totalpages, "pages=" & StringTrimLeft($outpage, 1)] 760 | Return $finaloutput 761 | EndIf 762 | EndFunc ;==>parsepage 763 | 764 | Func splitexpand($str, $pagecount = 3000) 765 | ;deal with z-1 and so on. 766 | ;$str example z-1 767 | ;;return an array two elements. array[0] is the selected pages count, array[1]is string pages=1,2,4,6,11-3 that pdfxcview can accept. 768 | ;$pagecount 3000 is not used. 769 | 770 | ; accept 2-10,11-3:even,r5-r2,z-1,3-z,-7,8-,11,z once a time. 771 | ;2-10 keep it is 772 | ;11-3:even expand to 10,8,6,4 773 | ;r5-r2 last 5 to last 2, expand to z-4,z-3,z-2,z-1 774 | ;z-1 all page in reverse order 775 | ;-7:even 2,4,6 776 | ;8- 8 to last pages 777 | ;11? 778 | ;11:even? 779 | 780 | $output = "" 781 | $tmpstr = "" 782 | $arraysplit = StringSplit($str, ":") 783 | 784 | ;deal with r3 and z by replacement and calculation 785 | $dashleft = StringLeft($arraysplit[1], -1 + StringInStr($arraysplit[1], "-")) 786 | $dashright = StringRight($arraysplit[1], StringLen($arraysplit[1]) - StringInStr($arraysplit[1], "-")) 787 | 788 | ;deal with single page such as z ,r1 789 | If StringInStr($arraysplit[1], "-") = 0 Then 790 | $dashleft = $dashright 791 | EndIf 792 | 793 | ;deal with string before - and after - 794 | If StringLower($dashleft) = "z" Or StringLower($dashleft) = "r1" Then 795 | $dashleft = $pagecount 796 | ElseIf StringLower(StringLeft($dashleft, 1)) = "r" And StringIsInt(StringTrimLeft($dashleft, 1)) Then 797 | $dashleft = $pagecount - StringRight($dashleft, StringLen($dashleft) - 1) + 1 798 | ElseIf $dashleft = "" Then 799 | $dashleft = 0 800 | EndIf 801 | 802 | If (StringLower($dashright) = "z" Or StringLower($dashright) = "r1") Or $dashright = "" Then 803 | $dashright = $pagecount + 1 804 | ElseIf StringLower(StringLeft($dashright, 1)) = "r" And StringIsInt(StringRight($dashright, StringLen($dashright) - 1)) Then 805 | $dashright = $pagecount - StringRight($dashright, StringLen($dashright) - 1) + 1 806 | EndIf 807 | 808 | If Not StringIsInt($dashleft) Or Not StringIsInt($dashright) Then Return SetError(1, 0, "Invalid page selector on the either side of -") ;invalid page selector on the either side of "-" 809 | 810 | ;expand 10-6 to 10,9,8,7,6 811 | If Number($dashright) < Number($dashleft) Then 812 | For $i = $dashleft To $dashright Step -1 813 | $output = $output & "," & $i 814 | Next 815 | ElseIf Number($dashright) >= Number($dashleft) Then 816 | For $i = $dashleft To $dashright 817 | $output = $output & "," & $i 818 | Next 819 | EndIf 820 | $output = StringTrimLeft($output, 1) 821 | 822 | ;singlepagearray contain separate page number. 823 | $singlepagearray = StringSplit($output, ",") 824 | 825 | ;remove page number greater than total pagecount or page number less than 1 826 | For $j = UBound($singlepagearray) - 1 To 1 Step -1 827 | If $singlepagearray[$j] > $pagecount Or $singlepagearray[$j] <= 0 Then _ArrayDelete($singlepagearray, $j) 828 | Next 829 | 830 | If UBound($arraysplit) = 3 Then ;existing odd or even seletor 831 | If StringLower($arraysplit[2]) = "even" Then 832 | For $j = UBound($singlepagearray) - 1 To 1 Step -1 833 | If $singlepagearray[$j] > $pagecount Or BitAND(Number($singlepagearray[$j]), 1) Then _ArrayDelete($singlepagearray, $j) 834 | Next 835 | ElseIf StringLower($arraysplit[2]) = "odd" Then 836 | For $j = UBound($singlepagearray) - 1 To 1 Step -1 837 | If $singlepagearray[$j] > $pagecount Or (Not BitAND(Number($singlepagearray[$j]), 1)) Then _ArrayDelete($singlepagearray, $j) 838 | Next 839 | Else 840 | Return SetError(2, 0, "Keyword error, not odd or even.") ;keyword error, not "odd" or "even" 841 | EndIf 842 | EndIf 843 | $output = "" 844 | 845 | ; Short 1,2,3,4,5,6 to 1-6 846 | For $j = 1 To UBound($singlepagearray) - 1 847 | $seperator = "," 848 | If $j >= 2 And Number($singlepagearray[$j]) = Number($singlepagearray[$j - 1]) + 1 Then 849 | $seperator = "-" 850 | If $j = UBound($singlepagearray) - 1 Then $output = $output & $seperator & $singlepagearray[$j] 851 | Else 852 | $output = $output & $seperator & $singlepagearray[$j] 853 | EndIf 854 | Next 855 | $output = StringTrimLeft($output, 1) 856 | Local $finaloutput[2] = [-2 + UBound(_ArrayUnique($singlepagearray)), $output] 857 | Return $finaloutput 858 | EndFunc ;==>splitexpand 859 | 860 | Func getfilematched($pdffile, $irecur, $pth = @ScriptDir) 861 | ;get a list of pdf files masked by $pdffile. 862 | ;$pdffile is a path containing mask, ie c:\windows\*.pdf, d:\???.pdf, must ended by .pdf. 863 | ;return an array contaning pdf file list, first element is the number of pdf files matched. 864 | ;$irecur=0 recur subflolder to unlimit depth. 865 | ;$irecur=1 recur this folder only 866 | ;$irecur=-x recur subfolder to x depth 867 | 868 | ;exand relative path to full path. 869 | $pdffile = _PathFull($pdffile) 870 | ;File name ended with .pdf otherwise exit. 871 | If StringLower(StringRight($pdffile, 4)) = ".pdf" Then 872 | $pth = StringMid($pdffile, 1, StringInStr($pdffile, "\", 0, -1)) 873 | $filter = StringTrimLeft($pdffile, StringInStr($pdffile, "\", 0, -1)) 874 | If $irecur = 0 Then 875 | ;Find all matching pdf file(s) in all sub folder(s). 876 | $aArray = _FileListToArrayRec($pth, $filter, $FLTAR_FILES, $FLTAR_RECUR, $FLTAR_NOSORT, $FLTAR_FULLPATH) 877 | ElseIf $irecur = 1 Then 878 | ;Find all matching pdf file(s) in this folder only. 879 | $aArray = _FileListToArray($pth, $filter, $FLTAR_FILES, True) 880 | ElseIf $irecur < 0 And IsInt($irecur) Then 881 | ;Find all matching pdf file(s) in one folder. 882 | $aArray = _FileListToArrayRec($pth, $filter, $FLTAR_FILES, $irecur, $FLTAR_NOSORT, $FLTAR_FULLPATH) 883 | Else 884 | Return SetError(1, 0, "getfilematched($pdffile,$irecur). Unsupported $irecur, only 0 or 1 or negative integer number are supported.") 885 | $code = 12 886 | Exit $code 887 | EndIf 888 | Else 889 | Return SetError(2, 0, "Error: [path]Filename must end with .pdf, but filename supports wildcard * and ?(path does not support wildcards.)") 890 | $code = 13 891 | Exit $code 892 | EndIf 893 | If $aArray = "" Then 894 | Return SetError(3, 0, "No pdf file matched.") 895 | EndIf 896 | 897 | Return $aArray 898 | EndFunc ;==>getfilematched 899 | 900 | Func qpdfgetpagecount($pdffilename, $pdfpassword = "", $qpdfdll = "qpdf29.dll") 901 | ;$pdffilename pdf file name full path only. 902 | ;$pdfpassword optional 903 | ;$qpdfdll location of qpdf29.DllCall 904 | ;return int pdf pagecount. negative number means pdf is encryped. 905 | $encrypted = 0 906 | If Not FileExists($pdffilename) Then 907 | Return SetError(1, 0, "Can't find " & $pdffilename & ".") 908 | EndIf 909 | 910 | If Not FileExists($qpdfdll) Then 911 | Return SetError(1, 0, "Can't find " & $qpdfdll & ".") 912 | EndIf 913 | 914 | ;Create a pointer to pdf filename since qpdf29.dll supoorts only ansi encoding, 915 | ; but convert utf8 string to ansi string directly may cause file not found error, 916 | ; especially when filename contain no ascii characters. 917 | Local $pdffilenameHex = StringToBinary($pdffilename, 4) 918 | Local $BufferSize = StringLen($pdffilenameHex) * 2 919 | Local $pdffilenameptr = DllStructCreate("byte[" & $BufferSize & "]") 920 | DllStructSetData($pdffilenameptr, 1, $pdffilenameHex) 921 | 922 | Global $hDLL = DllOpen($qpdfdll) 923 | If $hDLL = -1 Then 924 | Return SetError(2, 0, "DllOpen() error: Can't open " & $qpdfdll & ".") ; msgbox(0,"","dllOpen() error") ;-1=dllopen() error. 925 | EndIf 926 | 927 | ;typedef struct _qpdf_data* qpdf_data; 928 | ;typedef struct _qpdf_error* qpdf_error; 929 | ; /* Returns dynamically allocated qpdf_data pointer; must be freed 930 | ; * by calling qpdf_cleanup. 931 | ; */ 932 | ; QPDF_DLL 933 | ; qpdf_data qpdf_init(); 934 | $qpdfhdl = DllCall($hDLL, "PTR:cdecl", "qpdf_init") 935 | ; above: Since the returned type is qpdf_data, which is a qpdf_data pointer, can I use PTR? 936 | If @error Then 937 | DllClose($hDLL) 938 | Return SetError(3, 0, "Dllcall() qpdf_init error: error code: " & $qpdfhdl) 939 | EndIf 940 | 941 | ;typedef int QPDF_ERROR_CODE; 942 | ;# define QPDF_SUCCESS 0 943 | ;# define QPDF_WARNINGS 1 << 0 944 | ;# define QPDF_ERRORS 1 << 1 945 | ;/* Calling qpdf_read causes processFile to be called in the C++ 946 | ; * API. Basic parsing is performed, but data from the file is 947 | ; * only read as needed. For files without passwords, pass a null 948 | ; * pointer as the password. 949 | ; */ 950 | ; QPDF_DLL 951 | ; QPDF_ERROR_CODE qpdf_read(qpdf_data qpdf, char const* filename, 952 | ; char const* password); 953 | $pdfopen = DllCall($hDLL, "INT:cdecl", "qpdf_read", "PTR", $qpdfhdl[0], "PTR", DllStructGetPtr($pdffilenameptr), "STR", Null) ;pdf not encrypted no password is blank 954 | If @error Then 955 | cleanup($qpdfhdl[0], $hDLL) 956 | Return SetError(4, 0, "Dllcall() qpdf_read error. error code: " & $pdfopen) 957 | EndIf 958 | 959 | ;QPDF_DLL 960 | ;QPDF_BOOL qpdf_is_encrypted(qpdf_data qpdf); 961 | If $pdfopen[0] <> 0 Then 962 | $pdfencrypt = DllCall($hDLL, "Boolean:cdecl", "qpdf_is_encrypted", "PTR", $qpdfhdl[0]) 963 | If @error Then 964 | cleanup($qpdfhdl[0], $hDLL) 965 | Return SetError(4, 0, "Dllcall() qpdf_is_encrypted error. error code: " & $pdfencrypt) 966 | EndIf 967 | If $pdfencrypt[0] Then $encrypted = 1 968 | Else ;pdf is encrypted but password is blank. 969 | $encrypted = 0 970 | EndIf 971 | 972 | If $encrypted Then 973 | If $pdfpassword <> "" Then 974 | $pdfopen = DllCall($hDLL, "INT:cdecl", "qpdf_read", "PTR", $qpdfhdl[0], "PTR", DllStructGetPtr($pdffilenameptr), "STR", $pdfpassword) 975 | ;Else 976 | ;Return SetError(4, 0, "PDF file has password, but no password provided.") 977 | EndIf 978 | EndIf 979 | If @error Then 980 | cleanup($qpdfhdl[0], $hDLL) 981 | Return SetError(4, 0, "Dllcall() qpdf_read error. error code: " & $pdfopen) 982 | EndIf 983 | 984 | ; QPDF_DLL 985 | ; QPDF_BOOL qpdf_has_error(qpdf_data qpdf); 986 | $pdfhaserror = DllCall($hDLL, "Boolean:cdecl", "qpdf_has_error", "PTR", $qpdfhdl[0]) 987 | If @error Then 988 | cleanup($qpdfhdl[0], $hDLL) 989 | Return SetError(4, 0, "Dllcall() qpdf_has_error. error code: " & $pdfhaserror) 990 | EndIf 991 | If $pdfhaserror[0] Then 992 | ;QPDF_DLL 993 | ;qpdf_error qpdf_get_error(qpdf_data qpdf); 994 | $pdferror = DllCall($hDLL, "INT:cdecl", "qpdf_get_error", "PTR", $qpdfhdl[0]) 995 | $pdferrorcode = DllCall($hDLL, "INT:cdecl", "qpdf_get_error_code", "PTR", $qpdfhdl[0], "INT", $pdferror[0]) 996 | ;QPDF_DLL 997 | ;char const* qpdf_get_error_full_text(qpdf_data q, qpdf_error e); 998 | If $pdferrorcode[0] <> 4 Then ;encrypted pdf. 999 | $pdffullerror = DllCall($hDLL, "STR*:cdecl", "qpdf_get_error_full_text", "PTR", $qpdfhdl[0], "INT", $pdferror[0]) 1000 | Return SetError(4, 0, "QPDF open_pdf_has_error, PDF file might be corrupted. Error detail: " & @CRLF & $pdffullerror[0]) 1001 | EndIf 1002 | EndIf 1003 | 1004 | ; /* Object handling. 1005 | ; * 1006 | ; * These methods take and return a qpdf_oh, which is just an 1007 | ; * unsigned integer. The value 0 is never returned, which makes it 1008 | ; * usable as an uninitialized value. 1009 | ;QPDF_DLL 1010 | ;qpdf_oh qpdf_get_root(qpdf_data data); 1011 | $pdfroot = DllCall($hDLL, "INT:cdecl", "qpdf_get_root", "PTR", $qpdfhdl[0]) 1012 | If @error Then 1013 | cleanup($qpdfhdl[0], $hDLL) 1014 | Return SetError(5, 0, "Dllcall() qpdf_get_root error: error code: " & $pdfroot) 1015 | EndIf 1016 | 1017 | ; QPDF_DLL 1018 | ; QPDF_BOOL qpdf_oh_is_dictionary(qpdf_data data, qpdf_oh oh); 1019 | $pdfrootisdict = DllCall($hDLL, "boolean:cdecl", "qpdf_oh_is_dictionary", "PTR", $qpdfhdl[0], "int", $pdfroot[0]) 1020 | If @error Then 1021 | cleanup($qpdfhdl[0], $hDLL) 1022 | Return SetError(6, 0, "Dllcall() qpdf_oh_is_dictionary(RootIsDict) error: error code: " & $pdfrootisdict) 1023 | EndIf 1024 | 1025 | ; QPDF_DLL 1026 | ; QPDF_BOOL qpdf_oh_has_key(qpdf_data data, qpdf_oh oh, char const* key); 1027 | $pdfroothaskey = DllCall($hDLL, "boolean:cdecl", "qpdf_oh_has_key", "PTR", $qpdfhdl[0], "int", $pdfroot[0], "STR", "/Pages") 1028 | If @error Then 1029 | cleanup($qpdfhdl[0], $hDLL) 1030 | Return SetError(7, 0, "Dllcall() qpdf_oh_has_key(rootHas/Pages) error: error code: " & $pdfroothaskey) 1031 | EndIf 1032 | 1033 | ; QPDF_DLL 1034 | ; qpdf_oh qpdf_oh_get_key(qpdf_data data, qpdf_oh oh, char const* key); 1035 | $pdfpagesobjnum = DllCall($hDLL, "INT:cdecl", "qpdf_oh_get_key", "PTR", $qpdfhdl[0], "int", $pdfroot[0], "STR", "/Pages") 1036 | If @error Then 1037 | cleanup($qpdfhdl[0], $hDLL) 1038 | Return SetError(8, 0, "Dllcall() qpdf_oh_get_key(/Root/Pages) error: error code: " & $pdfpagesobjnum) 1039 | EndIf 1040 | 1041 | $pdfpagescount = DllCall($hDLL, "INT:cdecl", "qpdf_oh_get_key", "PTR", $qpdfhdl[0], "int", $pdfpagesobjnum[0], "STR", "/Count") 1042 | If @error Then 1043 | cleanup($qpdfhdl[0], $hDLL) 1044 | Return SetError(9, 0, "Dllcall() qpdf_oh_get_key(/Root/Pages/Count) error: error code: " & $pdfpagescount) 1045 | EndIf 1046 | 1047 | ; QPDF_DLL 1048 | ; char const* qpdf_oh_unparse_resolved(qpdf_data data, qpdf_oh oh); 1049 | $pdfPages = DllCall($hDLL, "STR*:cdecl", "qpdf_oh_unparse_resolved", "PTR", $qpdfhdl[0], "int", $pdfpagescount[0]) 1050 | If @error Then 1051 | cleanup($qpdfhdl[0], $hDLL) 1052 | Return SetError(9, 0, "Dllcall() qpdf_oh_unparse_resolved(/Root/Pages/Count) error: error code: " & $pdfPages) 1053 | EndIf 1054 | cleanup($qpdfhdl[0], $hDLL) 1055 | If $encrypted Then 1056 | Return 0 - $pdfPages[0] 1057 | Else 1058 | Return $pdfPages[0] 1059 | EndIf 1060 | EndFunc ;==>qpdfgetpagecount 1061 | 1062 | Func cleanup($qpdfhdl, $hDLL) 1063 | ;cleanup qpdf handle and dll handle 1064 | ;$qpdfhdl is a qpdf pointer 1065 | ;$hdll is a dll handle. 1066 | 1067 | ; /* Pass a pointer to the qpdf_data pointer created by qpdf_init to 1068 | ; * clean up resources. 1069 | ; */ 1070 | ; QPDF_DLL 1071 | ; void qpdf_cleanup(qpdf_data* qpdf); 1072 | $qpdfcleanup = DllCall($hDLL, "NONE:cdecl", "qpdf_cleanup", "PTR*", $qpdfhdl) ; PTR will crash, but PTR* not why? 1073 | DllClose($hDLL) 1074 | EndFunc ;==>cleanup 1075 | 1076 | Func ExecutableNameFlag($flagname) 1077 | ; 1078 | ; The application will behave differently based on it's filename. 1079 | ; The user can rename it to trigger some features. 1080 | ; 1081 | Return StringInStr(@ScriptName, $flagname) 1082 | EndFunc ;==>ExecutableNameFlag 1083 | 1084 | Func CLIMode() 1085 | Return $cli == 1 1086 | EndFunc ;==>CLIMode 1087 | 1088 | Func Display($message) 1089 | ; 1090 | ; The application can be run on CLI mode or GUI mode. 1091 | ; When in CLI mode we write to the console. 1092 | ; When in GUI mode display a message box. 1093 | ; 1094 | If CLIMode() Then 1095 | ConsoleWrite($message) 1096 | Else 1097 | If $silent = 0 Then MsgBox(0, $msgTitle, $message) 1098 | EndIf 1099 | EndFunc ;==>Display 1100 | 1101 | Func Flash($message) 1102 | If CLIMode() Then 1103 | ConsoleWrite($message) 1104 | Else 1105 | If $silent = 0 Then MsgBox(0, $msgTitle, $message, 2) 1106 | EndIf 1107 | EndFunc ;==>Flash 1108 | -------------------------------------------------------------------------------- /PDFtoPrinter.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emendelson/pdftoprinter/2fa5d5d0dfc7b0c4db5163529de6b3f93d56ea25/PDFtoPrinter.exe -------------------------------------------------------------------------------- /PDFtoPrinterWinSeven.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emendelson/pdftoprinter/2fa5d5d0dfc7b0c4db5163529de6b3f93d56ea25/PDFtoPrinterWinSeven.exe -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pdftoprinter 2 | AutoIt project for a PDF-to-printer application for Windows. 3 | 4 | Also installable with `winget install pdftoprinter`. 5 | 6 | This application is described in detail here: 7 | 8 | https://mendelson.org/pdftoprinter.html 9 | 10 | This respository includes the files needed for compiling and running the application. They should be copied to the same folder that contains the au3 file. 11 | 12 | Note that this application includes the freely-distributable but copyrighted commercial software PDF-Xchange Viewer from Tracker Software. 13 | 14 | 19 October 2024: The compiled version of the app and the source code now require 64-bit Windows. The older 32-bit version of the app and source code are still available; both have `32` in their filenames. 15 | 16 | If you get an error message about qpdf##.dll, then download and install the x86 version of the Microsoft VC redistributables from this page: https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170#latest-microsoft-visual-c-redistributable-version 17 | 18 | Malware detection: Some anti-malware programs will report that my installer contains malware; this happens because the AutoIt scripting language has been used to create malware and anti-malware programs block anything created in AutoIt. If you don't trust my software, don't use my software! Find something else instead. (Or compile it yourself from the code in this repository.) 19 | 20 | **You may not need this program at all.** Powershell can print PDF files from the command line. For example, to print to a specific printer, use: 21 | 22 | `Start-Process -FilePath "path\to\file" -Verb PrintTo -ArgumentList "Name of Printer" -PassThru | %{sleep 10;$_} | kill` 23 | 24 | To print to the default printer: 25 | 26 | `Start-Process -FilePath "path\to\file" -Verb Print -PassThru | %{sleep 10;$_} | kill` 27 | 28 | -------------------------------------------------------------------------------- /Settings.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emendelson/pdftoprinter/2fa5d5d0dfc7b0c4db5163529de6b3f93d56ea25/Settings.dat -------------------------------------------------------------------------------- /msvcp140.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emendelson/pdftoprinter/2fa5d5d0dfc7b0c4db5163529de6b3f93d56ea25/msvcp140.dll -------------------------------------------------------------------------------- /msvcp140_1.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emendelson/pdftoprinter/2fa5d5d0dfc7b0c4db5163529de6b3f93d56ea25/msvcp140_1.dll -------------------------------------------------------------------------------- /msvcp140_2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emendelson/pdftoprinter/2fa5d5d0dfc7b0c4db5163529de6b3f93d56ea25/msvcp140_2.dll -------------------------------------------------------------------------------- /msvcp140_atomic_wait.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emendelson/pdftoprinter/2fa5d5d0dfc7b0c4db5163529de6b3f93d56ea25/msvcp140_atomic_wait.dll -------------------------------------------------------------------------------- /msvcp140_codecvt_ids.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emendelson/pdftoprinter/2fa5d5d0dfc7b0c4db5163529de6b3f93d56ea25/msvcp140_codecvt_ids.dll -------------------------------------------------------------------------------- /pdftoprinter.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emendelson/pdftoprinter/2fa5d5d0dfc7b0c4db5163529de6b3f93d56ea25/pdftoprinter.ico -------------------------------------------------------------------------------- /qpdf29.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emendelson/pdftoprinter/2fa5d5d0dfc7b0c4db5163529de6b3f93d56ea25/qpdf29.dll -------------------------------------------------------------------------------- /resource.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emendelson/pdftoprinter/2fa5d5d0dfc7b0c4db5163529de6b3f93d56ea25/resource.dat --------------------------------------------------------------------------------