Seite 1 von 2

PDF Datei auf Drucker ausgeben

Verfasst: Di, 15. Jun 2021 20:01
von georg
Guten Abend,


ich suche gerade nach einer Möglichkeit, eine PDF-Datei, die auf dem Computer vorhanden ist, z.B. über RunShell() auf einem an den PC angeschlossenen Drucker auszugeben. Acrobat kann zwar angezeigt werden, sollte aber nach dem Druck automatisch schliessen.

Also, die Datei "C:\Temp\Kunden.pdf" soll auf dem Drucker "HPLaserJet 2500" ausgedruckt werden.

Also kein direktes Xbase++ Problem, sondern eher die Frage, wie stosse ich das an?

Theoretisch sollte das z.B. so gehen:

Code: Alles auswählen

"c:\program files(x86)\Adobe\Acrobat\DC\Acrobat.exe" /n /s /o /h /p "c:\temp\kunden.pdf" /t "HPLaserJet 2500"
Die Schalter haben folgende Bedeutung:

/n - neue Instanz starten
/s - keinen Splash-Screen anzeigen
/o - keinen Open File Dialog anzeigen
/h - minimiert anzeigen

Das Interessante hier ist, dass die Datei gedruckt wird, Acrobat aber meldet
Beim Öffnen dieses Dokuments ist ein Fehler aufgetreten. Diese Datei kann nicht gefunden werden.
Ich bin auch offen für Vorschläge bezüglich eines anderen Programms, aber es sollte im Bach möglich sein, ohne dass ein Bedienereingriff erforderlich ist oder das druckende Programm geschlossen werden muss.

Re: PDF Datei auf Drucker ausgeben

Verfasst: Di, 15. Jun 2021 20:28
von ramses
Hallo Georg

wären die Druckfunktionen der DebenuQuickPDF.dll nicht eine Variante?

Re: PDF Datei auf Drucker ausgeben

Verfasst: Di, 15. Jun 2021 20:35
von georg
Hallo, Carlo -


ja, aber zu teuer. Nach Möglichkeit mit Bordmitteln. Für ein privates Projekt zu kostspielig.

Re: PDF Datei auf Drucker ausgeben

Verfasst: Di, 15. Jun 2021 20:42
von AUGE_OHR
georg hat geschrieben: Di, 15. Jun 2021 20:01 ich suche gerade nach einer Möglichkeit, eine PDF-Datei, die auf dem Computer vorhanden ist, z.B. über RunShell() auf
statt RunShell mit ShellExecute

Code: Alles auswählen

   lSuccess := ShellExecute( 0, ;
                             "print", ;  77 DRUCKEN
                             cPath + cFILE, ;
                             cPara, ;
                             cHome, ;
                             SW_NORMAL
)

Re: PDF Datei auf Drucker ausgeben

Verfasst: Di, 15. Jun 2021 21:01
von ramses
Hallo Georg

benutzt du ot4xb? Oder ist dies ein NO GO für dich?

Re: PDF Datei auf Drucker ausgeben

Verfasst: Di, 15. Jun 2021 21:08
von Jan
Georg,

mit der PDF-Klasse von Edgar bekommst DU die Ex-Debenu, jetzt FoxIt-Dll. Zu einem sehr, sehr moderaten Preis.

Jan

Re: PDF Datei auf Drucker ausgeben

Verfasst: Di, 15. Jun 2021 22:03
von georg
Hallo,


erst einmal "danke" an Jimmy für das Beispiel, werde ich morgen ausprobieren.

Carlo, OT4XB setze ich ein. Das gehört für mich zu den "Bordmitteln" (ich weiss, manche sehen das anders).

Jan, "danke" für Deinen Hinweis, wenn ich anders nicht zu Potte komme, sehe ich mir das mal an.

Re: PDF Datei auf Drucker ausgeben

Verfasst: Mi, 16. Jun 2021 1:06
von Werner_Bayern
Servus Georg,

Wir gehen so vor:

- Default-Drucker in Windows auf gewünschten Drucker setzen
- Liste aller offenen Fenster ermitteln, sind potenzielle PDF-Programme darin enthalten, eine Meldung anzeigen, ob diese automatisch geschlossen werden dürfen
- shellexecuteA mit Parameter Print für die PDF
- Windows Default-Drucker wieder zurücksetzen

Funktioniert seit Jahren einwandfrei.

Re: PDF Datei auf Drucker ausgeben

Verfasst: Mi, 16. Jun 2021 8:52
von Marcus Herz
Dem Foxit PDF Reader kann in der shellexecute Anweisung über Parameter der Drucker mitgegeben werden. Das funktioniert auch:
https://kb.foxitsoftware.com/hc/en-us/a ... arameters-
Man kann dann im Hintergrund unabhängig von offnen Acrobat Readern oder Standardrucker arbeiten

Re: PDF Datei auf Drucker ausgeben

Verfasst: Mi, 16. Jun 2021 15:16
von Klaus Schuster
Sieh Dir einmal SumatraPDF an. Läuft bei meinen Kunden seit Jahren völlig problemlos.

Re: PDF Datei auf Drucker ausgeben

Verfasst: So, 20. Jun 2021 21:29
von georg
Guten Abend,


aktuell arbeite ich mal ab, was ich so an Hinweisen bekommen habe. Dabei tritt ein sehr seltsamer Fehler auf ...

Code: Alles auswählen

fExists(cAcrobat)    // ergibt .T., die Variable enthält Laufwerk, Pfad und Programmnamen
RunShell(, cAcrobat, .T.)     // ergibt einen OS Error 2 - "file not found"
Das ist das Fehlerprotokoll:

Code: Alles auswählen

------------------------------------------------------------------------------
FEHLERPROTOKOLL von "C:\Entwicklungen\Version.P02\demo.exe" Datum: 20.06.2021 21:19:26

Xbase++ Version     : Xbase++ (R) Version 2.00.1440
Betriebssystem      : Windows 10 2009 Build 19043
------------------------------------------------------------------------------
oError:args         :
          -> VALTYPE: U VALUE: NIL
          -> VALTYPE: C VALUE: "C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe"
          -> VALTYPE: L VALUE: .T.
oError:canDefault   : J
oError:canRetry     : J
oError:canSubstitute: N
oError:cargo        : NIL
oError:description  : Betriebssystemfehler
oError:filename     :
oError:genCode      :         40
oError:operation    : RunShell
oError:osCode       :          2
oError:severity     :          2
oError:subCode      :          4
oError:subSystem    : BASE
oError:thread       :          3
oError:tries        :          1
------------------------------------------------------------------------------
CALLSTACK:
------------------------------------------------------------------------------
Aufgerufen von PRINTPDF(86)
Aufgerufen von (B)GETTYPELIST(110)
Aufgerufen von PRINTFOUNDENTRY(574)
Aufgerufen von (B)SEARCHCONTENTDO(506)
Aufgerufen von SEARCHCONTENTDO(538)
Aufgerufen von (B)SEARCHCONTENT(70)
Kopiere ich den Inhalt der Variablen (sie enthält die Anführungszeichen am Anfang und Ende des Strings) ins Clipboard und füge es in der Befehlseingabe ein, wird der Acrobat Reader aufgerufen. Wie geschrieben, ein fExists() bestätigt ebenfalls, dass es die Datei gibt.

Nehme ich die Anführungszeichen weg, tritt der gleiche Fehler auf. Sieht jemand, was ich übersehe?

Re: PDF Datei auf Drucker ausgeben

Verfasst: So, 20. Jun 2021 22:06
von ramses
Hallo Georg

wenn in deinem Filenamen ( cAcrobat ) Leerzeichen vorkommen musst im String am Anfang und Ende Anführungszeichen haben.

Re: PDF Datei auf Drucker ausgeben

Verfasst: So, 20. Jun 2021 22:35
von georg
Hallo, Carlo -


ich habe beides versucht, sowohl mit als auch ohne die Anführungszeichen. In beiden Fällen bekomme ich den gleichen Fehler.

Re: PDF Datei auf Drucker ausgeben

Verfasst: So, 20. Jun 2021 23:27
von Werner_Bayern
Servus Georg,

darüber sind wir kürzlich (auch?) gestolpert: Ein

Code: Alles auswählen

file('"existierende_Datei"')
gibt .t. zurück, aber vieles andere für den Zugriff funktioniert nicht! Wir filtern jetzt bei Dateinamen - die gespeichert werden - ein evtl. " am Anfang und Ende raus.

Der Windows-Explorer akzeptiert dagegen schon Dateinamen in Anführungszeichen... Wir und unsere Kunden nutzen oft die Funktion im Explorer Shift-rechte Maustaste / als Pfad kopieren. Wird das dann in ein SLE eingefügt, hatten wir das Dilemma...

Re: PDF Datei auf Drucker ausgeben

Verfasst: So, 20. Jun 2021 23:46
von AUGE_OHR
hi,
georg hat geschrieben: So, 20. Jun 2021 21:29 aktuell arbeite ich mal ab, was ich so an Hinweisen bekommen habe. Dabei tritt ein sehr seltsamer Fehler auf ...

Code: Alles auswählen

fExists(cAcrobat)    // ergibt .T., die Variable enthält Laufwerk, Pfad und Programmnamen
RunShell(, cAcrobat, .T.)     // ergibt einen OS Error 2 - "file not found"
warm legst du dich "fest" auf ein Produkt mit RunShell() :roll:

ShellExecuteA() ruft doch die "verknüpfte" App auf für die entsprechende Extension.
"Open" und "Print" sind als Verb üblicherweise vorhanden und EDGE, welcher default verknüpft ist, kann auch PDF drucken.

Tip : statt SW_NORMAL kann man auch SW_HIDE verwenden

Re: PDF Datei auf Drucker ausgeben

Verfasst: Mo, 21. Jun 2021 0:27
von Werner_Bayern
AUGE_OHR hat geschrieben: So, 20. Jun 2021 23:46 "Open" und "Print" sind als Verb üblicherweise vorhanden und EDGE, welcher default verknüpft ist, kann auch PDF drucken.
Kann er so nicht... Schon mal probiert?

Re: PDF Datei auf Drucker ausgeben

Verfasst: Mo, 21. Jun 2021 0:35
von AUGE_OHR
Werner_Bayern hat geschrieben: Mo, 21. Jun 2021 0:27
AUGE_OHR hat geschrieben: So, 20. Jun 2021 23:46 "Open" und "Print" sind als Verb üblicherweise vorhanden und EDGE, welcher default verknüpft ist, kann auch PDF drucken.
Kann er so nicht... Schon mal probiert?
wenn der EDGE der "default" Browser ist und keine PDF "Verknüpfung" vorhanden ist klappt es bei mir mit Windows 11 :wink:

p.s. ich verwende Sumatra PDF wo es einen Wrapper gibt ( native ). auch Pablo hat einen Wrapper im Angebot.
mit den Wrapper kann man Sumatra.EXE "per" DllCall() aus einer App "steuern"

Re: PDF Datei auf Drucker ausgeben

Verfasst: Mo, 21. Jun 2021 7:26
von georg
Guten Morgen -


also, ich habe anhand der Registry ermittelt, welches Programm zum Einsatz kommt, ich lege mich also nicht auf ein bestimmtes Produkt fest, sondern nehme das vorgegebene Produkt, das im Windows-System eingestellt ist - ich bin gerade dabei, die unterschiedlichen Lösungswege durchzuspielen.

Und - auch der Hinweis auf die Wankelmütigkeit von fExists() ist gut. Aber mit dem String aus meinem Programm kann ich aus der Befehlseingabe den Acrobat Reader öffnen, d.h. daraus würdde ich schliessen, dass der String korrekt ist. Weshalb aber gibt es einen OS Code 2?

Re: PDF Datei auf Drucker ausgeben

Verfasst: Mo, 21. Jun 2021 13:25
von Werner_Bayern
Servus Georg,

probiers aus, zumindest unter Xbase++ funktioniert das nicht. Deshalb haben wir unsere Dateinamen-SLEs so umgeschrieben:

Code: Alles auswählen

oXbp:dataLink := {|x| if(.not. x == NIL .and. left(x, 1) == '"' .and. right(alltrim(x), 1) == '"', x := substr(x, 2, len(alltrim(x)) - 2), ),;

Re: PDF Datei auf Drucker ausgeben

Verfasst: Mo, 21. Jun 2021 13:28
von Werner_Bayern
AUGE_OHR hat geschrieben: Mo, 21. Jun 2021 0:35 wenn der EDGE der "default" Browser ist und keine PDF "Verknüpfung" vorhanden ist klappt es bei mir mit Windows 11 :wink:
Wir hatten letzte Woche bei einem Server-Umzug genau das Problem, der Terminalserver hatte kein Acrobat installiert, unser shellexecuteA rufte also PDFs mit Parameter Print auf, es gab keinen Ausdruck. Standard-Verknüpfung war Edge. Acrobat Reader installiert, alles läuft.

Wir schlossen daraus, dass Edge einen Aufruf einer PDF mittels PRINT nicht unterstützt.

Re: PDF Datei auf Drucker ausgeben

Verfasst: Di, 22. Jun 2021 4:05
von AUGE_OHR
hi,
Werner_Bayern hat geschrieben: Mo, 21. Jun 2021 13:28 Wir hatten letzte Woche bei einem Server-Umzug genau das Problem, der Terminalserver hatte kein Acrobat installiert, unser shellexecuteA rufte also PDFs mit Parameter Print auf, es gab keinen Ausdruck. Standard-Verknüpfung war Edge. Acrobat Reader installiert, alles läuft.

Wir schlossen daraus, dass Edge einen Aufruf einer PDF mittels PRINT nicht unterstützt.
lässt sich die PDF mit EDGE öffnen und drucken :?:

hatte der TS schon den "neuen" EDGE :?: welche OS Version :?:
bei der "älteren" EDGE Version sind Problem beim drucken von PDF bekannt

---

@Georg
üblicherweise gibt es zu einer App die Verknüpfung der Extension.
wenn keine Verknüpfung, wie bei *.DBF, existiert kann ein Aufruf nicht klappen

in der Registry "zu suchen" mit "was" eine Extension verknüpft ist wäre "doppelte Arbeit"
wenn keine Verknüpfung vorhanden ist gibt ShellExecute() den Fehler 31 (SE_ERR_NOASSOC) zurück den man so abfangen kann

Code: Alles auswählen

      CASE lSuccess = SE_ERR_NOASSOC                                  // Keine verknüЃpfte Anwendung
         // Falls ShowOpenWithDialog = True, wird der Dialog
         // "öffnen mit" für diese Datei angezeigt:
         // Shell "RunDLL32 shell32.dll,OpenAs_RunDLL " & Filename

         DllCall( "SHELL32.DLL", DLL_STDCALL, "OpenAs_RunDLL", ;
                  APPDESKTOP() :GetHWND(), ;
                  0, ;
                  cPath + cFile, ;
                  0, ;
                  CURDIR(), ;
                  SW_NORMAL )   

Re: PDF Datei auf Drucker ausgeben

Verfasst: Di, 22. Jun 2021 8:08
von brandelh
In einem Programm zeige ich Hinweis-PDF per Auswahlmenü an, dort nutze ich den hinterlegten PDF Reader:

Code: Alles auswählen

*------------------------------------------------------------- ZeigHinweise() -------------------------
function ZeigHinweise()
   local aHinweise, aPDFDateien, aTemp

   aTemp := directory(Hilfstabellenverzeichnis()+"*.PDF")

   if ! empty(aTemp)
      aPDFDateien := {}       // tats„chlicher Dateiname
      aEval(aTemp,{|aFileInfo| aadd(aPDFDateien,convToOEMCP(aFileInfo[1])) })
   else
      InfoBox("Es wurden keine Hinweise hinterlegt.")
   endif

   if ! empty(aPDFDateien)
      aHinweise := Auswahlliste(aPDFDateien," Hinweistexte")
   endif

   if ! empty(aHinweise)
      if " " $ aHinweise[1]
         infobox("Der Dateiname '"+aHinweise[1]+"' enth„lt Leerzeichen."+CRLF+;
                 "Dies ist nicht erlaubt. Bitte H. Brandel anrufen (1288) !")
      else
         RunShell( '/C START '+Hilfstabellenverzeichnis()+convToANSICP(aHinweise[1]),,.t.,.t. ) // das ist noch eine OEM EXE !
      endif
   endif

return nil
da das unter Citrix läuft, bisher bei jeder Version und auf meinen Test Rechnern auch sollte das allgemein gültig sein.
Ich habe mir es einfach gemacht und die erstellten PDF Dateien sowie den Pfad dazu ohne Leerzeichen geschrieben, wenn es welche gibt, müsste das so aussehen:

Code: Alles auswählen

         cDQ := chr(34)
         RunShell( '/C START '+cDQ+Hilfstabellenverzeichnis()+convToANSICP(aHinweise[1])+cDQ  ,  , .t. , .t. )
wenn fExist(cPDF) .t. ergibt, dann sind da vorne und Hinten KEINE Anführungszeichen !

Re: PDF Datei auf Drucker ausgeben

Verfasst: Di, 22. Jun 2021 8:39
von brandelh
In dieser Anwendung (ANSI EXE !) klicke ich auf einen Button, der diese Methode aufruft, aktuell hab ich auch eine Fehlermeldung, aber von Acrobat Reader DC, dass er die PDF nicht finden kann ... mal sehen

Code: Alles auswählen

*---------------------------------------------------------------------------
METHOD _dlgWellerBasis_ERW:ZeigBehandlungsplan()
   local cPfad := GetPfadBehandlungsplan()
   local cPDF  := "Behandlungsplan_"+(::BASERHAU)->WE_KEY+".PDF"
   local cEXE
   do case
      case empty(cPfad)
           msgbox("Pfad zu den Behandlungsplänen wurde noch nicht festgelegt")
      case ! fExists(cPfad+cPDF)
           msgbox("PDF existiert nicht:"+CRLF+cPfad+cPDF)
      otherwise
           cEXE := GetStandardProgramm(cPDF,cPfad)
           RunShell( cPfad+cPDF, cExe, .t. )
           setAppFocus(SetAppWindow())
   endcase

RETURN NIL
ja peinlich, da sind jetzt in der INI doch tatsächlich Blanks, also fehlen die cDQ ;-)

geändert und nun geht es:

Code: Alles auswählen

*---------------------------------------------------------------------------
METHOD _dlgWellerBasis_ERW:ZeigBehandlungsplan()
   local cPfad := GetPfadBehandlungsplan()
   local cPDF  := "Behandlungsplan_"+(::BASERHAU)->WE_KEY+".PDF"
   local cEXE
   local cDQ   := chr(34)
   do case
      case empty(cPfad)
           msgbox("Pfad zu den Behandlungsplänen wurde noch nicht festgelegt")
      case ! fExists(cPfad+cPDF)
           msgbox("PDF existiert nicht:"+CRLF+cPfad+cPDF)
      otherwise
           cEXE := GetStandardProgramm(cPDF,cPfad)

           RunShell( cDQ+cPfad+cPDF+cDQ, cExe, .t. )

           setAppFocus(SetAppWindow())
   endcase

RETURN NIL
Wichtig, fExists fragt den Namen mit Pfad OHNE " ab, erst bei Runshell() wird es ergänzt.

Code: Alles auswählen

*--------------------------------------------------------------------------
FUNCTION GetStandardProgramm(cFile, cPath)
   LOCAL cExe := ChrR(0,260) // MAX_PATH is 260
   IF @shell32:FindExecutableA(cFile, cPath, @cExe) < 32
      cExe := ""
   ELSE
      cExe := TrimZ(cExe)
   END
RETURN cExe
*-----------------------------------------------------------------------------
FUNCTION GetPfadBehandlungsplan()
   local cPfad := GetProgIni("Behandlungsplan", "Pfad", "")
   if ! empty(cPfad)
      if right(cPfad,1) # "\"
         cPfad += "\"
      endif
   endif
Return cPfad

* in XB_API.PRG
#include "Dll.ch"
DLLFUNCTION FindExecutableA( cF, cP, @cE ) USING STDCALL FROM SHELL32.DLL
DLLFUNCTION GetPrivateProfileStringA(cSection, cVar, cDefault, @cBuffer, nBufferLen, cFileName) USING STDCALL FROM KERNEL32.DLL
DLLFUNCTION WritePrivateProfileStringA(cSection, cVar, cValue, cFileName)                       USING STDCALL FROM KERNEL32.DLL

Re: PDF Datei auf Drucker ausgeben

Verfasst: Di, 22. Jun 2021 8:48
von brandelh
georg hat geschrieben: So, 20. Jun 2021 21:29 Guten Abend,
aktuell arbeite ich mal ab, was ich so an Hinweisen bekommen habe. Dabei tritt ein sehr seltsamer Fehler auf ...

Code: Alles auswählen

fExists(cAcrobat)    // ergibt .T., die Variable enthält Laufwerk, Pfad und Programmnamen
RunShell(, cAcrobat, .T.)     // ergibt einen OS Error 2 - "file not found"
Schau dir mal meinen Beitrag direkt über diesem an, bei mir ist das zwar cEXE aber das ist vermutlich nicht das Problem.
Auch ich habe bei der EXE keine Anführungszeichen, aber bei der Syntax muss man links vorne die PDF mit Pfad und Anführungszeichen angeben.

Re: PDF Datei auf Drucker ausgeben

Verfasst: Fr, 24. Jun 2022 12:26
von Schorsch
Hallo Hubert,
ich habe jetz auch die von Dir verwendete Funktion (FUNCTION GetStandardProgramm(cFile, cPath)) probiert um herauzubekommen,was das Standard-PDF Programm ist, bekomme aber nur einen leeren String als Ergebnis.
Kannst Du vielleicht erläutern,was ich überprüfen muss um ein brauchbares Ergebnis zu bekommen?
Danke