Chuan
Chuan

Reputation: 469

How to print PDF files in a sequence using Powershell?

I have a bunch of PDF files that I would like to print in sequence on a windows 7 computer using Powershell.

get-childItem "*.pdf" | sort lastWriteTime | foreach-object {start-process $._Name -verb 'print'}

The printed files are sometimes out of order like 1) A.pdf, 2) C.pdf, 3) B.pdf 4) D.pdf.

Different trials printed out a different sequence of files, thus, I fear the error is related to the printing queue or the start-process command. My guess is that each printing process is fired without waiting for the previous printing process to be completed.

Is there a way to consistently print out PDF files in a sequence that I specify?

Upvotes: 1

Views: 3778

Answers (2)

Martin
Martin

Reputation: 1

My solution (4 years later) is as follows: The command first gets a list of all the needed file and selects the first one and waits for the print-queue to be empty, next it does the actual printing of the selected file, and then it waits for the print-queue to not be empty, because it might take a little before Adobe starts the printing. And that is repeated for each selected file.

@("file1*.pdf","file3*.pdf","file6*.pdf") | %{gci $_} | sort Name | foreach-object {while (@(Get-Printer | Get-PrintJob).Count -gt 0) {Start-Sleep -S 3;write-Host . -NoNewline};Write-Host "";Write-Host $_.Name;start-process -FilePath $_.fullname -verb 'print';while (@(Get-Printer | Get-PrintJob).Count -eq 0) {Start-Sleep -S 1;write-Host . -NoNewline}}

Upvotes: 0

Matthew
Matthew

Reputation: 1166

You are starting the processes in order, but by default Start-Process does not wait until the command completes before it starts the next one. Since the commands take different amounts of time to complete based on the .PDF file size they print in whatever order they finish in. Try adding the -wait switch to your Start-Process, which will force it to wait until the command completes before starting the next one.

EDIT: Found an article elsewhere on Stack which addresses this. Maybe it will help. https://superuser.com/questions/1277881/batch-printing-pdfs

Additionally, there are a number of PDF solutions out there which are not Adobe, and some of them are much better for automation than the standard Reader. Adobe has licensed .DLL files you can use, and the professional version of Acrobat has hooks into the back end .DLLs as well.

If you must use Acrobat Reader DC (closed system or some such) then I would try opening the file to print and getting a pointer to the process, then waiting some length of time, and forcing the process closed. This will work well if your PDF sizes are known and you can estimate how long it takes to finish printing so you're not killing the process before it finishes. Something like this:

ForEach ($PDF in (gci "*.pdf"))
{
    $proc = Start-Process $PDF.FullName -PassThru
    Start-Sleep -Seconds $NumberOfSeconds
    $proc | Stop-Process
}

EDIT #2: One possible (but untested) optimization is that you might be able use the ProcessorTime counters $proc.PrivilegedProcessorTime and $proc.UserProcessorTime to see when the process goes idle. Of course, this assumes that the program goes completely idle after printing. I would try something like this:

$LastPrivTime = 0
$LastUserTime = 0
ForEach ($PDF in (gci "*.pdf"))
{
    $proc = Start-Process $PDF.FullName -PassThru
    Do
    {
        Start-Sleep -Seconds 1
        $PrivTimeElapsed = $proc.PrivilegedProcessorTime - $LastPrivTime
        $UserTimeElapsed = $proc.UserProcessorTime - $LastUserTime
        $LastPrivTime = $proc.PrivilegedProcessorTime
        $LastUserTime = $proc.UserProcessorTime
    } 
    Until ($PrivTimeElapsed -eq 0 -and $UserTimeElapsed -eq 0)
    $proc | Stop-Process
}

If the program still ends too soon, you might need to increase the # of seconds to sleep inside the inner Do loop.

Upvotes: 2

Related Questions