manrique
Goto Top

PDF mit Powershell nochmals drucken

Hallo an alle,

aktuell muss ich ein pdf file aus einer "Fremdanwendung" nochmals drucken, weil dieses in einer bestimmten Konstellation (Adobe Acrobat Reader DC und meistens aber nicht immer HP Drucker) NICHT ausgedruckt werden kann! Da eine Umstellung auf (zb. Foxit - damit funktioniert der Druck) wegen der hohen Clientanzahl und Kundenwunsch (Acrobat) derzeit keine Lösung ist, brauche ich eine andere (wenn auch nicht schöne) Lösung:

Das bestehende pdf via powershell nochmal auf einen "PDF-Drucker" senden - dann funktioniert der Druck auch mit Acrobat DC Reader.

# Drucker definieren
$printer = 'Microsoft Print to PDF'  
$pdf = "C:\Users\xyz\Documents\Test.pdf"  
gci "C:\Users\xyz\Documents\Test.pdf" | %{  
    # starte PDF-Druck via Shell-Verb 'printto' 
    $pdfApp = (start-process $_.FullName -Verb "printto" -PassThru -ArgumentList "$printer").ProcessName  
    # initialer sleep
    sleep(3)
    # loope solange bis Datei freigegeben wurde und lösche sie dann
    #while($true){del $_ -Force -EV err -EA SilentlyContinue; If($err){sleep(1)}else{break}}
}

# PDF Applikation beenden
get-process $pdfApp -ErrorAction SilentlyContinue | Stop-Process

PDF via Powershell drucken - Reader nach druck schließen
Ich hab versucht den Code zu ändern, komme aber zu keinem Ergebnis. Wenn möglich (kein Fehler weil schon vorhanden) soll das "original-pdf" OHNE Dialog (filename) überschrieben werden, sonst neuer Name Test_new.pdf
$pdfApp = (start-process -FilePath $pdf -Verb "printto" -PassThru -ArgumentList "$printer").ProcessName hat auch nicht funktioniert.

Kann mir bitte jemand helfen?

Vielen Dank
Manrique

Content-ID: 625164

Url: https://administrator.de/forum/pdf-mit-powershell-nochmals-drucken-625164.html

Ausgedruckt am: 25.12.2024 um 08:12 Uhr

beidermachtvongreyscull
beidermachtvongreyscull 23.11.2020 um 15:54:16 Uhr
Goto Top
Moin,

ich bin jetzt nicht der Powershell-Papst, aber für mich sieht der Code so aus, dass Du zwar drumherum automatisierst, aber innerhalb der Anwendung bzw. des Druckertreibers nicht und ich nehme an, dass mindestens einer davon eine Nutzereingabe haben will, die nicht kommt.

Kann das sein?

Dann läge die Wurzel des Übels darin, dass Du nicht alle Nutzerinteraktionen per Script eingefangen hast.

Wie wäre ein alternativer Ansatz?

Die Fremdanwendung scheint ja PDFs zu erzeugen, die nicht ganz dem Standard entsprechen und somit vom Platzhirsch schlichtweg nicht verarbeitet werden.

Wenn Du die Möglichkeit in Betracht ziehst, dass die PDFs korrumpiert sein können, dann versuche es doch mal mit PDFtk:
http://www.techiesguide.com/repair-pdf-files-using-the-pdf-toolkit-pdft ...

Das ließe sich vielleicht leichter per Script steuern.

Gruß
bdmvg
Manrique
Manrique 23.11.2020 um 19:08:10 Uhr
Goto Top
PDFtk ist keine Option.

Ich hab auf Basis des Codes von Colinardo versucht das zu realisieren, funktioniert - jedoch kommt noch der Dialog "Druckausgabe speichern unter".

Was muss ich ändern, damit das ursprüngliche pdf OHNE Dialog überschrieben wird?

gci "C:\Users\xyz\Documents\Test.pdf" | Print-PDF -printer "Microsoft Print to PDF" #-DeleteAfterPrint  
<#
     ==== @colinardo  / @administrator.de ====
#>
function Print-PDF {
    param(
        [parameter(mandatory=$true,ValueFromPipelineByPropertyName=$true)][Alias("Fullname")][ValidateNotNullOrEmpty()][string[]]$files,  
        [ValidateScript({(gwmi Win32_Printer -Filter "Name='$_'")})][string]$printer  
        #[switch]$DeleteAfterPrint
    )
    begin{
        # set printer if defined in parameter
        if ($printer -ne ''){  
            # store original printer
            $originalPrinter = gwmi Win32_Printer -Filter "Default='true'"  
            # set default printer temporarily to defined printer
            [void](gwmi Win32_Printer -Filter "Name='$printer'").SetDefaultPrinter()  
        }

        # function to check file lock state
        $CheckFileStatus = {
            param([string]$filePath)
            try{
                $fileStream = (New-Object System.IO.FileInfo $filePath).OpenWrite()
                $fileStream.Close(); $fileStream.Dispose()
                # file is not locked by another process
                return $true
            }catch{
                # file is locked
                return $false
            }
        }
        $pdfAppID = $null
    }
    process{
        $files | %{
            write-host "Printing document: '$_' ..." -ForegroundColor Green  
            # start printing pdf with default print-handler in the system
            $pdfApp = (start-process $_ -Verb "print" -PassThru).ProcessName  
            # sleep time  / increase this parameter in case files get not printed
            sleep(3)
            # check file-lock-status in loop until it's free  
            while(!(&$CheckFileStatus $_)){sleep(1)}
            # delete file if desired by user
            #if ($DeleteAfterPrint.IsPresent()){
            #    write-host "Deleting document: '$_' ..." -ForegroundColor Yellow  
            #    del $_ -Force
            #}
        }
    }
    end{
        # kill pdf viewer process
        get-process $pdfApp -EA SilentlyContinue | Stop-Process

        if ($printer -ne ''){  
            #restore original default printer
            [void]$originalPrinter.SetDefaultPrinter()
        }
    }
}
beidermachtvongreyscull
beidermachtvongreyscull 23.11.2020 um 20:09:03 Uhr
Goto Top
BIN DRAUẞEN!
TK1987
TK1987 24.11.2020 um 14:08:41 Uhr
Goto Top
Moin,

Zitat von @Manrique:
Was muss ich ändern, damit das ursprüngliche pdf OHNE Dialog überschrieben wird?
afaik bietet "Microsoft Print to Pdf" kein speichern ohne Dialog an.
Um das zu realisieren, müsstest du also auf einen anderen PDF-Drucker umsteigen.

Gruß Thomas
Manrique
Manrique 24.11.2020 um 15:06:00 Uhr
Goto Top
Hallo Thomas,

mit folgendem Code bekomm ich KEINEN Dialog, jedoch wird ein leeres/weißes pdf generiert:

    gci "C:\Users\xyz\Documents\Testanhang.pdf" | Print-PDF -DocumentPath "C:\Users\xyz\Documents\Testanhang.pdf" #-DeleteAfterPrint  

function Print-PDF {
	param(
		$DocumentPath
	)
	
	Add-Type -AssemblyName System.Drawing
	$doc = New-Object System.Drawing.Printing.PrintDocument
	$doc.DocumentName = $DocumentPath
	$doc.PrinterSettings = new-Object System.Drawing.Printing.PrinterSettings
	$doc.PrinterSettings.PrinterName = 'Microsoft Print to PDF'  
	$doc.PrinterSettings.PrintToFile = $true
	$file=[io.fileinfo]$DocumentPath
	$pdf= [io.path]::Combine($file.DirectoryName, $file.BaseName) + '.pdf'  
	$doc.PrinterSettings.PrintFileName = $pdf
	$doc.Print()
	$doc.Dispose()
}

Kann auch ein anderer PDF-Drucker sein. Soll auf Windows Server 2019 laufen. Hab's auch schon mit SumatraPDF versucht. Funktioniert bei mir nur mit DIALOG - hab bei den Printing options kein -printToFile bzw. PrintFileName gefunden.

Danke schon mal für weitere Hilfe
Manrique
Manrique 25.11.2020 um 16:14:04 Uhr
Goto Top
Hallo an alle,

ich hab jetzt eine funktionierende Lösung mit dem PDF Creator OHNE Dialog!

# create printable PDF
# Drucker definieren
$printer = 'PDFCreator'  
gci "C:\Users\xyz\Documents\Test.pdf" | %{  
    # starte PDF-Druck via Shell-Verb 'printto' 
    $pdfApp = (start-process $_ -Verb "printto" -PassThru -ArgumentList "$printer").ProcessName  
    #$pdfApp = (start-process $_ -Verb "print" -PassThru).ProcessName 
    # initialer sleep
    sleep(3)
    # loope solange bis Datei freigegeben wurde und lösche sie dann - erledige ich zu einem späteren Zeitpunkt: PDF wird vorher noch transferiert
    #while($true){del $_ -Force -EV err -EA SilentlyContinue; If($err){sleep(1)}else{break}}
}

# PDF Applikation beenden
get-process $pdfApp -ErrorAction SilentlyContinue | Stop-Process
sleep(3)
Stop-Process -Name architect -ErrorAction SilentlyContinue

Ursprüngliches PDF wird mit Adobe Acrobat Reader DC geöffnet und an den Drucker PDF Creator geschickt. Es wird zwar dann auch noch der PDF Architect geöffnet, welcher in der letzten Zeile auch wieder beendet wird.

Danke an alle und LG
Manrique