fr4nki
Goto Top

PDF via Powershell drucken - Reader nach druck schließen

Hallo Zusammen,

ich habe ein Powershell Skript geschrieben, dass mir Archive entpackt und die darin enthaltenen PDF-Dateien druckt.
Das klappt ganz gut, jedoch soll das Skript die Dateien nach dem Drucken wieder löschen.
Aktiviere ich die Lösch-Funktion, so klappt das ganz nicht mehr, denn das Powershell Skript geht hin und setzt den Druckbefehl ab und löscht darauf hin die Datei sofort, bevor diese ausgedruckt wurde.
Nun würd ich ja ein Wait-Process einbauen, jedoch schließt sich das Reader Programm nach dem Druck leider nicht von alleine.
Ich habe bisher den Foxit-PDF Reader und den Adobe PDF Reader ausprobiert.

Kann mir jemand von euch ein Programm nennen, dass sich nach dem Drucken automatisch schließt, sodass man es überwachen kann.
Oder kann mir jemand von euch sagen wie ich das im Skript realisieren kann?

Viele Grüße
Fr4nki

Content-Key: 257659

Url: https://administrator.de/contentid/257659

Ausgedruckt am: 29.03.2024 um 14:03 Uhr

Mitglied: TlBERlUS
TlBERlUS 15.12.2014 aktualisiert um 09:56:10 Uhr
Goto Top
Hi,

Reader-Prozess beenden?

https://www.google.de/?gws_rd=ssl#q=powershell+prozess+beenden

Grüße,

Tiberius
Mitglied: Doskias
Doskias 15.12.2014 um 09:56:55 Uhr
Goto Top
Jetzt ohne dein Skript zu kennen fällt mir nur die Holzhammer-Methode ein:

taskkill /IM AcroRd32.exe

Ansonsten poste hier das Skript um eine vernünftige Lösung zu erhalten face-smile
Mitglied: Fr4nki
Fr4nki 15.12.2014 um 10:38:50 Uhr
Goto Top
Es geht mir eigentlich darum zu wissen wie ich prüfen kann wann die Datei gedruckt wurde. Somit das Skript erst danach zum löschen übergeht.

Also das hier ist das Skript:

function entpackenunddrucken() {

$printer = $($args[1]).Substring(11,4)
$tempverz = "C:\in1\temp\" + $printer
$archiv = "C:\in1\DONE"
$entpackverz = "-o" + $tempverz

  1. Entpacken
cd "C:\7-Zip"
./7z.exe e $($args) $entpackverz *.pdf -r
move-item $($args) $archiv
start-sleep -s 1

  1. Drucken
cd $tempverz
ForEach( $File in Get-ChildItem ) {
#C:\Adobe\Reader\Reader\AcroRd32.exe /N /T $File.FullName $printer
C:\Foxit\FoxitReader.exe /t $File.Fullname $printer
Remove-Item $File.Fullname
} }

  1. Funktionsaufruf
cd C:\in1
ForEach( $File in Get-ChildItem ) { if ($File.Name -like "*.tar") { entpackenunddrucken $File.Fullname $File.Name } }
Mitglied: TlBERlUS
TlBERlUS 15.12.2014 aktualisiert um 11:39:46 Uhr
Goto Top
Wenn du nicht gerade win win 8 oder Server 2012 hast, könntest du mit

Get-CimInstance win32_printjob
(gwmi win32_printer).printerstatus

versuchen zu basteln. Ist allerdings(imho) fehleranfällig, wenn du auf erfolgreichen Druck-Auftrag prüfen willst.
Mitglied: colinardo
Lösung colinardo 16.12.2014, aktualisiert am 30.11.2020 um 23:17:52 Uhr
Goto Top
Hallo Fr4nkie,
ich mach das mit dem Adobe (Reader oder Acrobat) immer so:
# Drucker definieren
$printer = 'HP Laserjet 1320'  
gci "C:\Ordner\*.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
oder wenn stattdessen nur das Verb print im System vorhanden ist, dann so:
$printer = 'HP Laserjet 1320'  
# store original printer
$originalPrinter = gwmi Win32_Printer -Filter "Default='true'"  
# Set Default Printer
[void](gwmi Win32_Printer -Filter "Name='$printer'").SetDefaultPrinter()  

gci "C:\Ordner\*.pdf" | %{  
    $pdfApp = (start-process $_.FullName -Verb "print" -PassThru).ProcessName  
    sleep(3)
    while($true){del $_ -Force -EV err -EA SilentlyContinue; If($err){sleep(1)}else{break}}
}
get-process $pdfApp -ErrorAction SilentlyContinue | Stop-Process

#restore original default printer
[void]$originalPrinter.SetDefaultPrinter()

habe das ganze mal in eine Function gepackt:
back-to-topFunktion: Print-PDF
<#
     ==== @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 $_.FullName -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()
        }
    }
}
Diese lässt sich dann folgendermaßen verwenden:
back-to-topBeispiele
Drucken auf anderen Drucker mit anschließendem Löschen des PDFs
gci "C:\Ordner\*.pdf" | print-pdf -printer "HP Laserjet 1320" -DeleteAfterPrint
Drucken auf Default-Printer ohne Löschen
gci "C:\Ordner\*.pdf" | print-pdf

Zur Info: Bei Bedarf den sleep Parameter in Zeile 40 anpassen, wenn die Dateien nicht gedruckt werden.

Grüße Uwe
Mitglied: Andinistrator1
Andinistrator1 13.04.2015 aktualisiert um 15:29:23 Uhr
Goto Top
Super Sache! Funktioniert mit Netzlaufwerk und -drucker.

Ich hab es mit Adobe probiert. Hier öffnet sich das Programm, druckt und schließt wieder. Kann man das noch unterdrücken oder gibt es ein besseres PDF Tool für diesen Zweck?

Wie ist der Code für *.HTM Daten? Der Internexexplorer ist schon drauf, d.h. ich könnte auf Adobe verzichten.
Mitglied: colinardo
colinardo 13.04.2015, aktualisiert am 30.11.2020 um 23:18:44 Uhr
Goto Top
Hallo Andinistrator,
Zitat von @Andinistrator1:
Ich hab es mit Adobe probiert. Hier öffnet sich das Programm, druckt und schließt wieder. Kann man das noch
unterdrücken oder gibt es ein besseres PDF Tool für diesen Zweck?
Lässt sich eventuell machen, muss ich nachher erst mal testen ...
-edit- Acrobat wie so viele andere Apps ignorieren hier das man sie unsichtbar öffnen möchte..., aber das Fenster ist ja eigentlich minimiert (zumindest Acrobat bei mir) so dass das ja bei einem unbeaufsichtigten System eigentlich egal ist.

Wie ist der Code für *.HTM Daten? Der Internexexplorer ist schon drauf, d.h. ich könnte auf Adobe verzichten.
Der IE ist hier mal wieder speziell wegen Sicherheit & Co.

Du kannst aber mal das hier probieren, das den Druckdialog mit einem Enter "fernsteuert":
/(Bei Bedarf die sleep-Zeiten an dein System anpassen)//
# Drucker auf dem gedruckt werden soll
$printer = 'HP Laserjet 1320'  
# Original Drucker speichern
$originalPrinter = gwmi Win32_Printer -Filter "Default='true'"  
# Set Default Printer
[void](gwmi Win32_Printer -Filter "Name='$printer'").SetDefaultPrinter()  
$objShell = New-Object -Com Wscript.Shell

gci "C:\Ordner\*.html" | %{  
    start-process $_.Fullname -Verb "print" -PassThru  
    sleep(2)
    $objShell.SendKeys("{ENTER}")  
    sleep(1)
    while($true){del $_ -Force -EV err -EA SilentlyContinue; If($err){sleep(1)}else{break}}
}

# Original Standarddrucker wiederherstellen
[void]$originalPrinter.SetDefaultPrinter()
Grüße Uwe
Mitglied: Andinistrator1
Andinistrator1 14.04.2015 um 12:43:44 Uhr
Goto Top
Vielen Dank, dass sieht gut aus. Sleep auf 5 und es wird automatisch gedruckt.

Gibt es noch einen fixen Parameter für

- Querformat (statt Hoch)
- ohne Kopfzeile (Seite 1 von 1 wird gedruckt)
- ohne Fußzeile (Quelle und Datum wird gedruckt)?


Beim PDF Script haben auch Netzwerkdrucker funktioniert, welche über ein Druckserver mit meinem Server verbunden sind. Das hier nun nicht mehr zu klappen. Wenn der Drucker lokal auf dem Server eingerichtet ist, aber schon.

Netzwerk-Laufwerke werden aber weiterhin ausgelesen.
Mitglied: colinardo
colinardo 14.04.2015 aktualisiert um 12:52:10 Uhr
Goto Top
Zitat von @Andinistrator1:
Gibt es noch einen fixen Parameter für

- Querformat (statt Hoch)
- ohne Kopfzeile (Seite 1 von 1 wird gedruckt)
- ohne Fußzeile (Quelle und Datum wird gedruckt)?
Nein. Ebenfalls nur über Tastenfernsteuerung, aber das wird dann unzuverlässig.
Beim PDF Script haben auch Netzwerkdrucker funktioniert, welche über ein Druckserver mit meinem Server verbunden sind. Das
hier nun nicht mehr zu klappen. Wenn der Drucker lokal auf dem Server eingerichtet ist, aber schon.
Normal ...Geht nur mit lokal eingerichteten Druckern, da dieser temporär als Standard gesetzt werden muss ...
Der IE kennt ja kein printto Verb, deshalb.
Netzwerk-Laufwerke werden aber weiterhin ausgelesen.
logisch ...
Mitglied: Andinistrator1
Andinistrator1 14.04.2015 um 14:25:19 Uhr
Goto Top
Ja also das PDF Script läuft einwandfrei, im Test hatte ich es nun doppelt laufen, d.h.

2 Ordnerpfade drucken auf
2 unterschiedliche Drucker

Hier hab ich nun auch Acrobat Reader (V2015.007.20033) probiert, hier geht das Fenster auf und zu, eine Minimierung beim Start hab ich nicht gefunden.

Manchmal verschluckt es sich aber, Datei nicht gefunden..., so als ob er schneller löscht wie er druckt. Ich hab den Sleep Wert auf 5 hochgesetzt, dann läuft es durch.

Thank you colinardo
Mitglied: JK23JK
JK23JK 12.11.2015 um 11:46:36 Uhr
Goto Top
Hallo Uwe,

ich habe gerade deinen INteressanten Beitrag hier empfohlen bekommen.
Und dein Script ist fast genau das was ich suche/ benötige.
Nur leider bin ich jetzt nicht gerade der Pro was PoweShell etc. angeht.

Könntest du mir bei zwei dingen auf die Sprünge helfen ?

Er soll anstatt einem gezielten den Standartdrucker des ausführenden verwenden
und er soll die PDF nach dem drucken nicht löschen sondern in C:\Test\Archiv verschieben:

Was muss ich wo wie editieren.

  1. Drucker definieren
$printer = 'HP Laserjet 1320'
gci "C:\Ordner\*.pdf" | %{
          1. starte PDF-Druck via Shell-Verb 'printto'
          $pdfApp = (start-process $_ -Verb "printto" -PassThru -ArgumentList "$printer").ProcessName
                  1. initialer sleep
                  sleep(3)
                          1. 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}}
                          }
                          1. PDF Applikation beenden
                          get-process $pdfApp -ErrorAction SilentlyContinue | Stop-Process


                          Vielen Dank vorab und sorry für die Anfänger Frage - aber iwie stehe ich auf dem Schlauch face-sad

                          Beste Grüße
Mitglied: thaefliger
thaefliger 01.12.2017 um 13:12:51 Uhr
Goto Top
Hallo @colinardo

ich bin gerade über diese wunderbare Powershell-Funktion von dir gestossen.
Nun habe ich kleines Problem, vielleicht hast du eine Idee:
wenn ich das Skript in der ISE ausführe, wird das PDF gedruckt und dann gelöscht.
Starte ich das Skript über einen geplanten Task, wird das PDF nicht gedruckt, aber gelöscht.

Execution-Policy hab ich zum Testen mal auf unrestricted gesetzt.

Grüsse
Thomas
Mitglied: colinardo
colinardo 01.12.2017 aktualisiert um 14:01:55 Uhr
Goto Top
Servus Thomas,
Welches Skript meinst du?
Welche Taskplanersettings wurden verwendet?
Der Drucker in dem Security-Kontext(Profil) des Taskplaners vorhanden sein, Drucker werden ja meist Userabhängig gemappt.
Muss ich dann erst evaluieren ob es Taskplanerfähig ist, und wenn dann liegt es an deinem Default PDF-Handler wenn die nicht ohne GUI klar kommt, oder das deine verwendete PDFApp Sicherheitstechnische Maßnahmen ergreift wenn Dokumente auf Netzlaufwerken bzw. unsicheren Quellen liegen.
Werde ich bei Zeiten nachholen/testen.
Mitglied: thaefliger
thaefliger 01.12.2017 um 14:37:27 Uhr
Goto Top
Hallo

ich meine dieses Skript:
<#
     ==== @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()
        }
    }
}

gci "C:\Hotfolder\files\*.pdf" | print-pdf -printer "Testdrucker" -DeleteAfterPrint  

Taskplaner (so ausm Kopf, bin schon aus dem Büro geflüchtet face-smile)
- mit höchsten Privilegien, unabhängig angemeldeter User
- Täglich alle 5 Minuten
- powershell.exe c:\Hotfolder\skript\pdfdrucken.ps1

Der Drucker ist ein Netzwerkdrucker, wurde aber lokal auf diesem Rechner installiert (kein Mapping via Printserver).
Default PDF Handler ist wohl Adobe Reader DC.
Mitglied: colinardo
colinardo 01.12.2017 aktualisiert um 16:38:31 Uhr
Goto Top
Fazit: "Adobe Reader DC" ist nicht für den Betrieb über den Task-Scheduler geeignet da es für den Prozess eine GUI benötigt, bzw. sich beim Aufruf über die Shell ohne Console-Session selbst beendet.

Nimm für den Druck ein Tool wie Sumatra pdf reader der unterstützt auch das Batch Commandline Printing.
https://www.sumatrapdfreader.org/docs/Command-line-arguments-0c53a79e913 ...
-print-to-default : Prints all files indicated on this command line to the system default printer. After printing, SumatraPDF exits immediately (check the error code for failure).

-print-to <printer-name> : Prints all files indicated on this command line to the named printer. After printing, SumatraPDF exits immediately (check the error code for failure). E.g. -print-to "Microsoft XPS Document Writer" prints all indicated files to the XPS virtual printer.
Mitglied: thaefliger
thaefliger 03.12.2017 um 21:14:10 Uhr
Goto Top
Danke dir!
Werde das am Montag gleich ausprobieren.
Mitglied: thaefliger
thaefliger 04.12.2017 um 15:11:26 Uhr
Goto Top
@colinardo
sorry, ich steh total auf dem Schlauch.
Wie integriere ich den SumatraPDF so in dein Skript, dass die PDF's mit diesem abgearbeitet werden?
Mitglied: colinardo
colinardo 04.12.2017 aktualisiert um 16:59:39 Uhr
Goto Top
Zitat von @thaefliger:

@colinardo
sorry, ich steh total auf dem Schlauch.
Wie integriere ich den SumatraPDF so in dein Skript, dass die PDF's mit diesem abgearbeitet werden?
Das Skript brauchst du doch nicht mehr face-smile. Du musst einfach nur alle zu druckenden Dokumente an das Programm übergeben, ob du das nun via Batch oder Powershell FOR-Schleife machst ist Jacke wie Hose:
Also so
gci "D:\Ordner\*.pdf" | %{ &'C:\Pfad\sumatrapdf.exe' -print-to "DeinDruckerName" "`"$($_.Fullname)`""}  
oder alternativ auch inline (nicht empfohlen bei vielen Dateien langen Namen und Pfaden, da das Kommandozeilen-Limit sonst zuschlägt!)
&'C:\Pfad\sumatrapdf.exe' -print-to "DeinDruckerName" "`"$((gci 'D:\Ordner\*.pdf' | select -Expand Fullname) -join '" "')`""  
oder eben als Batch
for %%a in ("D:\Ordner\*.pdf") do "C:\Pfad\sumatrapdf.exe" -print-to "DeinDruckerName" "%%a"  
Dachte du bist jemand der sich zumindest mal die Doku durchliest face-wink.
Mitglied: thaefliger
thaefliger 04.12.2017 um 16:35:14 Uhr
Goto Top
Danke dir.
Die Dokuseite hab ich gelesen. Mein Knopf war die "Integration" des Batch-Befehls für Sumatra in die Powershell-Zeile.
Mitglied: thaefliger
thaefliger 04.12.2017 um 18:46:44 Uhr
Goto Top
Sorry, noch eine letzte Frage:

im Original-Skript gabs für das "Druck-Kommando" noch den Paramter -DeleteAfterPrint
gci "C:\Hotfolder\files\*.pdf" | print-pdf -printer "Testdrucker" -DeleteAfterPrint  

Wie kann ich diesen Parameter hier integrieren?
gci "D:\Ordner\*.pdf" | %{ &'C:\Pfad\sumatrapdf.exe' -print-to "DeinDruckerName" "`"$($_.Fullname)`""}  

hab ein paar Sachen ausprobiert, leider ohne Erfolg.
Mitglied: colinardo
colinardo 04.12.2017 aktualisiert um 20:52:53 Uhr
Goto Top
Zitat von @thaefliger:
Wie kann ich diesen Parameter hier integrieren?
gci "D:\Ordner\*.pdf" | %{ &'C:\Pfad\sumatrapdf.exe' -print-to "DeinDruckerName" "`"$($_.Fullname)`""}  
So z.B.
$files = gci "D:\Ordner\*.pdf"   
$files | %{&'C:\Pfad\sumatrapdf.exe' -print-to "DeinDruckerName" "`"$($_.Fullname)`""}  
$files | remove-item -Force