Saturday | 20 APR 2024
[ previous ]
[ next ]

Programmatically Printing PDFs on Windows

Date: 2022-04-14

In theory, automatically printing pdfs should be easy on windows. After all opening a pdf and doing ctrl p works without issue. In practice, it was much harder and annoying than it needed to be.

I figured a quick powershell script would be all I need and I tried quite a few iterations of it and after much trial and error got it to work.

Stuff that didn't work:

> (New-Object -ComObject WScript.Network).SetDefaultPrinter('Test')
> $Printer = Get-WmiObject -Class Win32_Printer -Filter "(Name='PRINTER20')"
> $Printer.SetDefaultPrinter()

The below script did work but it required juggling the default printers and the script has to kill the process once it finishes printing. This is what the sleep is for.

> $OldPrinter = Get-WMIObject -Query " SELECT * FROM Win32_Printer WHERE Default=$true"
> $printer = Get-CimInstance -Class Win32_Printer -Filter "Name='PRINTER20'"
> Invoke-CimMethod -InputObject $printer -MethodName SetDefaultPrinter
> Start-Process -FilePath "C:\temp/some.pdf" -Verb Print -PassThru | %{sleep 5;$_} | kill
> $OldPrinter.SetDefaultPrinter()

To say this is hacky is an understatement! It seems that this is really an issue with adobe acrobat reader as that is the pdf viewer and it seems windows farms out the printing to it. This actually does make sense and I'm sure that there are some decent reasons for why things are the way they are. I also don't know powershell and I didn't really try to understand it so I looked for a way to do printing with something I'm comfortable with.

Enter Node! I looked on npm for a printing utility that would print pdfs for me and I found a package called print-to-pdf. Poking around the source showed that it was really a wrapper for sumatra pdf.

This was exactly what I was looking for! A small executable that I could drop in and use from the command line.

Ultimately I scrapped my powershell script and wrote a small script using sumatrapdf.

> .\SumatraPDF.exe -print-to PRINTER0 "C:\temp\some.pdf"

This works brilliantly and simply!