Out-PDFFile.ps1

function Out-PDFFile
{
  <#
      .SYNOPSIS
      Prints data to a PDF file using the PrintToPDF printer driver
 
      .DESCRIPTION
      Prints data to a printer called "PrintPDFUnattended" which prints the
      data to a static file in the temp folder without user interaction. The generated
      PDF file is then moved to a user-specified location.
      If the printer "PrintPDFUnattended" is not present, the function calls
      the dependent function Install-PDFPrinter. Requires Windows 10, Server 2016, or better.
 
      .PARAMETER Path
      Path to PDF file that is generated
 
      .PARAMETER Open
      When specified, the generated PDF file is opened in the associated PDF viewer (if one is available)
 
      .EXAMPLE
      Get-Process | Out-PDFFile -Path $home\Desktop\doc.pdf -Open
      Saves a process list to a PDF file called doc.pdf on the user desktop,
      and opens the file in the associated PDF viewer.
 
      .NOTES
      This function requires the function Install-PDFPrinter
  #>



  param
  (
    [string]$Path = "$env:temp\results.pdf",

    [Switch]
    $Open
  )

  function Install-PDFPrinter
  {
    <#
        .SYNOPSIS
        Installs a new Printer called "PrintPDFUnattended" which prints to file
 
        .DESCRIPTION
        Uses the built-in "PrintToPDF" printer driver to create a new printer
        that prints unattendedly to a fixed file in the temp folder
 
        .EXAMPLE
        Install-PDFPrinter
        Installs the printer "PrintPDFUnattended". Needs to be run only once.
        To remove the printer again, use this command:
        Remove-Printer PrintPDFUnattended
 
        .NOTES
        Requires the "PrintToPDF" printer driver shipping with Windows 10, Server 2016, or better
 
        .LINK
        URLs to related sites
        The first link is opened by Get-Help -Online Install-PDFPrinter
    #>



  
    $PrinterDefaultName = 'Microsoft Print to PDF'
    $printerName = 'PrintPDFUnattended'
    # choose a default path where the PDF is saved:
    $PDFFilePath = "$env:temp\PDFResultFile.pdf"
  

    # see whether the driver exists
    $ok = @(Get-PrinterDriver -Name $PrinterDefaultName -ea 0).Count -gt 0
    if (!$ok)
    {
      Write-Warning -Message "Printer driver 'Microsoft Print to PDF' not available."
      Write-Warning -Message 'This driver ships with Windows 10 or Server 2016.'
      Write-Warning -Message "If it is still not available, enable the 'Printing-PrintToPDFServices-Features'"
      Write-Warning -Message 'Example: Enable-WindowsOptionalFeature -Online -FeatureName Printing-PrintToPDFServices-Features'
      return
    }

    # check whether port exists
    $port = Get-PrinterPort -Name $PDFFilePath -ErrorAction SilentlyContinue
    if ($port -eq $null)
    {
      # create printer port
      Add-PrinterPort -Name $PDFFilePath 
    }

    # add printer
    Add-Printer -DriverName $PrinterDefaultName -Name $printerName -PortName $PDFFilePath 
  }
  # check to see whether the PDF printer was set up correctly
  $printerName = 'PrintPDFUnattended'
  $printer = Get-Printer -Name $printerName -ErrorAction SilentlyContinue
  if (!$?)
  {
    Install-PDFPrinter
    $printer = Get-Printer -Name $printerName -ErrorAction SilentlyContinue
  }

  # this is the file the print driver always prints to:
  $TempPDF = $printer.PortName

  # is the printer set up correctly and the port name is the output file path?
  if ($TempPDF -notlike '?:\*')
  {
    Write-Warning -Message "Printer $printerName is not set up correctly." 
    Write-Warning -Message 'Make sure you have created this printer as instructed (see previous tips)!'
    return
  }

  # make sure old print results are removed
  $exists = Test-Path -Path $TempPDF
  if ($exists) { Remove-Item -Path $TempPDF -Force }

  # send anything that is piped to this function to PDF
  $input | Out-Printer -Name $printerName

  # wait for the print job to be completed, then move file
  $ok = $false
  do { 
    Start-Sleep -Milliseconds 500 
    Write-Host '.' -NoNewline
                
    $fileExists = Test-Path -Path $TempPDF
    if ($fileExists)
    {
      try
      {
        Move-Item -Path $TempPDF -Destination $Path -Force -ErrorAction Stop
        $ok = $true
      }
      catch
      {
        # file is still in use, cannot move
        # try again
      }
    }
  } until ( $ok )
  Write-Host

  # open file if requested
  if ($Open)
  {
    Invoke-Item -Path $Path
  }
}