PDF-Dateien erstellen, bearbeiten, zusammenstellen usw. kann man mit GhostScript . Der Weg über die Kommandozeile erfordert immer zusätzlichen Ressourcen und manchmal auch zusätzliche Rechte (W2K3). Da ist der Zugriff über die DLL günstiger. Die kleine UDF _gs_dll_2PDF() in gs_dll.au3 organisiert das.
Die UDF _gs_dll_warg() kann direkt mit einem Array aufgerufen werden und so viele Dateien auf einmal zur Verabreitung entgegen nehmen (getestet mit 400 PDF-Dateien), auf der Kommandozeile ist nach 256 Zeichen Schluss.
Im Array können alle Parameter untergebracht werden, mit denen gswin32c.exe aufgerufen werden könnte (siehe die aktuelle Dokumentation ).
Spoiler anzeigen
;gs_dll.au3
#include-once
#include <Array.au3>
Opt("MustDeclareVars", 0)
exit
;===============================================================================
; Description: Anwendungsbeispiel
; Author(s): Tomas Dils
; Example: _gs_dll_2PDF("C:\ziel.pdf","C:\quelle1.ps","C:\quelle2.pdf,"C:\quelle3.eps")
; Parameter(s): $varPDAT - zu erstellende Datei (mit vollem Pfad)
; $varQDAT1 - eine bis zu sieben Quelldateien in den Formaten
; ... die GhostScript verarebieten kann, also .ps, .pdf
; $varQDAT7 und .eps
; Requirement(s): GhostScript ab Version 8.60 ordentlich installiert
; Note(s): Das erste Feld des $strARRAY kann beliebigen Inhalt haben.
; Die anderen Felder sollten mit sinnvollem Inhalt gefüllt sein.
; Das Array hat den Vorteil, dass bei der Konvertierung ver-
; schiedener Dateien nur die entsprechenden Felder neu bestimmt
; werden müssen. Durch das Anhängen von Feldern mit Quelldateien
; lassen sich viele Dateien (500 getestet) in einem Rutsch zusammenfassen.
;===============================================================================
Func _gs_dll_2PDF($varPDAT,$varQDAT1,$varQDAT2='',$varQDAT3='',$varQDAT4='',$varQDAT5='',$varQDAT6='',$varQDAT7='')
Local $strARRAY[15]
; Umgesetzte Kommandozeile
; " -q -dNOSAFER -sDEVICE=pdfwrite -dCompatibilityLevel=1.5 -o " & _
; $varZielDAT & " -c save pop .setpdfwrite -f " & $varQuellDatei1 & " " & $varQuellDatei2 , "", @SW_HIDE)
$strARRAY[0]="GS_DLL"
$strARRAY[1]="-q"
$strARRAY[2]="-dNOSAFER"
$strARRAY[3]="-sDEVICE=pdfwrite"
$strARRAY[4]="-dCompatibilityLevel=1.5"
$strARRAY[5]= "-dNumRenderingThreads=2" ;erst ab GhostScript Version 8.63, ohne dem Version 8.60
$strARRAY[6]="-r300"
$strARRAY[7]="-o"
$strARRAY[8]=""&$varPDAT&""
$strARRAY[9]="-c"
$strARRAY[10]="save"
$strARRAY[11]="pop"
$strARRAY[12]=".setpdfwrite"
$strARRAY[13]="-f"
$strARRAY[14]=FileGetShortName($varQDAT1)
For $I=2 TO @NUMPARAMS-1
IF FileExists(EVAL("varQDAT"&$I)) Then
_ArrayAdd($strARRAY, FileGetShortName(EVAL("varQDAT"&$I)))
EndIF
Next
; Ergänzung für die Linearisierung von PDF-Dateien
; If Not IsDeclared("$varGSC") Then Global $varGSC = _gs_dll_SuchGhostScript()
; IF FileExists(FileGetShortName(StringReplace($varGSC,"bin\win32c.exe","lib\pdfopt.ps"))) Then
; _ArrayAdd($strARRAY, "pdfopt.ps")
; EndIf
Local $varFehler=_gs_dll_warg($strARRAY)
If @error Then
MsgBox(16,"GS_DLL","Der Aufruf der Funktion _gs_dll_warg wurde mit folgender Fehlermeldung beendet:" & @CRLF & _
$varFehler & @CRLF & _
"Prüfen sie die Ergebnisse der weiteren Arbeit sorgfältig!")
EndIf
If FileExists($varPDAT) Then
Return 0
;~ ShellExecuteWait($varPDAT)
;~ FileDelete($varPDAT)
Else
MsgBox(0,"GS_DLL.au3 _gs_dll_2PDF","Die Zieldatei"&@CRLF&$varPDAT&@CRLF&"wurde nicht erstellt.")
Return SetError(1,0,$varFehler)
EndIf
EndFunc
;===============================================================================
; Description: Spricht die GS.DLL direkt an.
; Parameter(s): $strARRAY - alle Parameter als String
; Requirement(s): GhostScript ab Version 8.60 ordentlich installiert
; Return Value(s): On Success - 0 und @error=0
; On Failure - Fehlermeldung und @error=1
; Author(s): Tomas Dils
; Note(s): $varGSC mit dem vollständigen Pfad zu gswin32c.exe
; $varGSD mit dem vollständigen Pfad zu gswin32.dll
; $var_gs_dll_revision mit der Revisionsnummer der DLL
; können global definiert werden, um Zeit zu sparen.
;===============================================================================
Func _gs_dll_warg($strARRAY)
;GS_DLL finden
If Not IsDeclared("$varGSC") Then Global $varGSC = _gs_dll_SuchGhostScript()
If @error Then Return SetError(1,0,"Kein GhostScript gefunden.")
If Not IsDeclared("$varGSD") Then Global $varGSD =FileGetShortName(StringReplace($varGSC,"win32c.exe","dll32.dll"))
If Not FileExists($varGSD) Then
;MsgBox(0,"GS_DLL","Die Datei " & @CRLF & $varGSD & @CRLF & " wurde nicht gefunden.")
Return SetError(1,0,"Datei " & $varGSD & "existiert nicht.")
EndIf
;GS_DLL prüfen
If Not IsDeclared("$var_gs_dll_revision") Then Global $var_gs_dll_revision=_gs_dll_revision($varGSD)
If @error<>0 Then Return SetError(1,0,"Fehler bei Bestimmung der Revisionsnummer.")
If $var_gs_dll_revision<860 Then Return SetError(1,0,"GhostScript sollte mindestens Version 8.60 haben. Gefunden wurde " & $var_gs_dll_revision &".")
;Array säubern von leeren Einträgen
Local $_strARRAY[1]
For $I=1 To UBound($strARRAY)-1
Switch $strARRAY[$I]
Case "", " ", @TAB
Case Else
_ArrayAdd($_strARRAY,$strARRAY[$I])
EndSwitch
Next
;GS_DLL initialisieren
Local $dllGS= DllOpen($varGSD)
Local $GSInstanceHandle=DllStructCreate("int_ptr")
Local $pGSInstanceHandle=DllStructGetPtr($GSInstanceHandle)
If Not $dllGS<1 Then
Local $varErgebnis0 = DllCall($dllGS,"int","gsapi_new_instance","int_ptr",$pGSInstanceHandle,"int_ptr",0)
If ($varErgebnis0 < 0) Then
;~ MsgBox(0,"gs_dll.au3", "Die Initialisierung der" & @CRLF & _
;~ $varGSD & @CRLF & _
;~ "ist mit dem Ergebnis" & @CRLF & _
;~ $varErgebnis0 & @CRLF & _
;~ "gescheitert.")
return SetError(1,0,"Die Initialisierung der" & @CRLF & _
$varGSD & @CRLF & _
"ist mit dem Ergebnis" & @CRLF & _
$varErgebnis0 & @CRLF & _
"gescheitert.")
EndIf
Else
$pGSInstanceHandle=0
$GSInstanceHandle=0
Return SetError(1,0,"Initialisierung der GhostScript-DLL ist fehlgeschalgen.")
EndIF
Local $intGSInstanceHandle=DllStructGetData($GSInstanceHandle,1)
;=>GS_DLL initialisieren
Local $varVAR, $varByte
If IsArray($_strARRAY) Then
For $I=0 To UBound($_strARRAY)-1
$varVAR&="char["&Execute(StringLen($_strARRAY[$I])+1)&"];"
$varByte&="int_ptr;"
Next
$varVAR=StringTrimRight($varVAR,1)
$varByte=StringTrimRight($varByte,1)
Else
Return SetError(1,0)
EndIf
Local $byteArgs = DllStructCreate($varVAR)
Local $intptrArgs = DllStructCreate($varByte)
Local $intElementCount = UBound($_strARRAY)
;~ Dim $strStruc ;zum Test
For $I=1 To UBound($_strARRAY)
DllStructSetData($byteArgs,$I,CharToOEM($_strARRAY[$I-1]))
DllStructSetData($intptrArgs,$I,DllStructGetPtr($byteArgs,$I))
;~ $strStruc &= @CRLF & DllStructGetPtr($byteArgs,$I) & " " & Execute(8*StringLen($strARRAY[$I-1])+8) & " "& StringLen(_String2Binary($strARRAY[$I-1] & Chr(0))) & " "& DllStructGetData($byteArgs,$I)
Next
;~ MsgBox(0,"DllStructur", "Struct Size: " & DllStructGetSize($byteArgs) & @CRLF & _
;~ "Struct pointer: " & DllStructGetPtr($byteArgs) & @CRLF & _
;~ "Count pointer: " & DllStructGetPtr($intElementCount) & @CRLF & _
;~ "Data:" & DllStructGetData($intElementCount,1)& $strStruc )
Local $Ergebnis = DllCall($dllGS,"int","gsapi_init_with_args","ptr",$intGSInstanceHandle,"int",$intElementCount,"int_ptr", DllStructGetPtr($intptrArgs))
$byteArgs = 0
$intptrArgs = 0
$GSInstanceHandle=0
;DLL schließen, ohne dem kann die Ziel-Datei nicht weiter verarbeitet werden!
DllCall($dllGS,"int","gsapi_exit","ptr",$intGSInstanceHandle)
DllCall($dllGS,"int","gsapi_delete_instance","ptr",$intGSInstanceHandle)
If $dllGS > 0 Then DllClose($dllGS)
$dllGS = 0
;Rückmeldung
If $Ergebnis[0]=0 OR $Ergebnis[0]="e_Quit" Then
Return SetError(0,0)
Else
Return SetError(1,0,_ArrayToString($Ergebnis," | "))
EndIf
EndFunc
;===============================================================================
; Description: Gibt die Versionsnummer der übergebenen GS.DLL zurück.
; Parameter(s): $_varGSD - Vollständiger Pfad und Name der DLL als String
; Requirement(s): None
; Return Value(s): On Success - Die Revisionsnummer und @error=0
; On Failure - @error=1 Abfrage ging fehl
; @error=2 Datei existiert nicht
; Author(s): Tomas Dils
; Note(s): es könnte noch das Datum zurückgegeben werden
; Produktname und Copyright sind fehlerhaft angesprochen/ausgewertet
;===============================================================================
Func _gs_dll_revision($_varGSD)
If Not FileExists($_varGSD) Then Return SetError(2,0)
Local $gsapi_revision=DllStructCreate("int_ptr product;int_ptr copyright;long revision;long revisiondate")
Local $charProduct=DllStructCreate("char[32]")
DllStructSetData($gsapi_revision,"product",DllStructGetPtr($charProduct))
Local $charCopyright=DllStructCreate("char[32]")
DllStructSetData($gsapi_revision,"copyright",DllStructGetPtr($charCopyright))
Local $p_gsapi_revision=DllStructGetPtr($gsapi_revision)
Local $s_gsapi_revision= DllStructGetSize($gsapi_revision) ; muss 16 sein
Local $varErgebnis = DllCall($_varGSD,"int","gsapi_revision","int_ptr",$p_gsapi_revision,"int",$s_gsapi_revision)
Local $varRevision=DllStructGetData($gsapi_revision,"revision")
;~ MsgBox(0,"TEST",_ArrayToString($varErgebnis," | ") & @CRLF & _
;~ "Größe:" & @TAB & @TAB & $s_gsapi_revision & @CRLF & _
;~ "Produkt:" & @TAB & @TAB & DllStructGetData($charProduct,1) & @CRLF & _
;~ "CopyRight:" & @TAB & DllStructGetData($charProduct,1) & @CRLF & _
;~ "Version:" & @TAB & @TAB & $varRevision & @CRLF & _
;~ "Datum:" & @TAB & @TAB & DllStructGetData($gsapi_revision,"revisiondate"))
$gsapi_revision=0
$charProduct=0
$charCopyright=0
If $varErgebnis[0]=0 Then
Return SetError(0,0,$varRevision)
Else
Return SetError($varErgebnis[0],0,$varRevision)
EndIf
EndFunc ;=> _gs_dll_revision
;===============================================================================
; Description: GhostScript zu Fuß
; Parameter(s): $_strARRAY - Parameter als String oder als Array
; - wenn leer, wird der Hilfetext angezeigt
; $_intTimeOut - Sekunden bis zum Abbruch
; - Vorgabewert 120 Sekunden
; Requirement(s): Gobale $varGSC mit vollständiger Pfad und Name der gswin32c.exe
; als String oder _gs_dll_SuchGhostScript
; Return Value(s): On Success - StdOut und @error=0
; On Failure - StdOut und StdErr und @error=1
; Author(s): Tomas Dils
; Note(s): gut zum Testen, da Rückmeldung als Text
;===============================================================================
Func _gs_dll_RunGSC($_strARRAY="-h",$_intTimeOut=120)
Local $strLine, $strError
If Not IsDeclared("$varGSC") Then
Global $varGSC = _gs_dll_SuchGhostScript()
If @error Then Return SetError(1,0,"Kein GhostScript gefunden.")
ElseIf Not FileExists($varGSC) Then
Global $varGSC = _gs_dll_SuchGhostScript()
If @error Then Return SetError(1,0,"Kein GhostScript gefunden.")
EndIf
If IsArray($_strARRAY) Then
Local $varProzess=Run($varGSC &" " & _ArrayToString($_strARRAY," ",1),"",@SW_HIDE,BitOR(4,2))
Else
Local $varProzess=Run($varGSC &" " & $_strARRAY,"",@SW_HIDE,BitOR(4,2))
EndIf
While 1
$strError &= StderrRead($varProzess)
If @error Then ExitLoop
$strLine &= StdoutRead($varProzess)
If @error Then ExitLoop
Wend
StdioClose($varProzess)
ProcessWaitClose($varProzess,$_intTimeOut) ; was nach 2 Minuten nicht geworden ist, wird wohl auch nicht mehr werden
If ProcessExists($varProzess) Then ProcessClose($varProzess)
IF $strError="" Then
IF $_strARRAY="-h" Then MsgBox(32,"_gs_dll_RunGSC", $strLine)
Return SetError(0,0,$strLine)
Else
MsgBox(16,"_gs_dll_RunGSC", $strLine & @CRLF & $strError)
Return SetError(1,0,$strLine & @CRLF & $strError)
EndIf
EndFunc
;===============================================================================
; Description: GhostScript suchen
; Parameter(s): $varGSV - optional Mindestversion Parameter als Integer oder String
; Requirement(s): _gs_dll_fProgDateiVorhanden
; Return Value(s): On Success - vollständiger Pfad zur aktuellsten Version der gswin32c.exe
; On Failure - 0
; Author(s): Tomas Dils [email='dils@arcor.de'][/email]
; Note(s):
;===============================================================================
Func _gs_dll_SuchGhostScript($varGSV = 863)
Local $varVER
; weil man ja nicht mit jeder neuen GhostScriptVersion das Programm ändert
For $varI = 1 To 100
$varVER = RegEnumKey("HKLM\SOFTWARE\GPL Ghostscript\", $varI)
If @error <> 0 Then
$varVER = StringReplace(RegEnumKey("HKLM\SOFTWARE\GPL Ghostscript\", $varI - 1), ".", "")
If $varGSV < $varVER Then $varGSV = $varVER
ExitLoop
EndIf
Next
$varGSV = StringTrimRight($varGSV, 2) & "." & StringRight($varGSV, 2)
;damit insbesondere IrfanView auch auf GhostScript zugreifen kann
Local $varAFPL=RegRead("HKLM\SOFTWARE\GPL Ghostscript\"&$varGSV,"GS_DLL")
RegWrite("HKLM\SOFTWARE\AFPL Ghostscript\"&$varGSV,"GS_DLL","REG_SZ",$varAFPL)
$varAFPL=RegRead("HKLM\SOFTWARE\GPL Ghostscript\"&$varGSV,"GS_LIB")
RegWrite("HKLM\SOFTWARE\AFPL Ghostscript\"&$varGSV,"GS_LIB","REG_SZ",$varAFPL)
Local $varDateiName = "gs\gs" & $varGSV & "\bin\gswin32c.exe"
Local $varDateiPfad = "C:\"
Select
Case FileExists($varDateiPfad & "\" & $varDateiName)
Return $varDateiPfad & "\" & $varDateiName
Case FileExists(@ProgramFilesDir & "\" & $varDateiName)
Return @ProgramFilesDir & "\" & $varDateiName
Case FileExists(@CommonFilesDir & "\" & $varDateiName)
Return @CommonFilesDir & "\" & $varDateiName
Case FileExists(@WindowsDir & "\" & $varDateiName)
Return @WindowsDir & "\" & $varDateiName
Case FileExists(@SystemDir & "\" & $varDateiName)
Return @SystemDir & "\" & $varDateiName
Case FileExists(@ScriptFullPath & "\" & $varDateiName)
Return @ScriptFullPath & "\" & $varDateiName
Case FileExists(@WorkingDir & "\" & $varDateiName)
Return @WorkingDir & "\" & $varDateiName
Case FileExists(@TempDir & "\" & $varDateiName)
Return @TempDir & "\" & $varDateiName
Case Else
MsgBox(16, "GD_DLL Fehlermeldung", "Das Programm " & $varDateiName & Chr(10) & " wurde nicht im erwarteten Pfad " & $varDateiPfad & " gefunden.")
Return 0
EndSelect
EndFunc ;==>_SuchGhostScript
; #FUNCTION# ====================================================================================================================
; Name...........: _gs_dll_SDateiName()
; Description ...: gibt einen noch nicht belegten seriellen Dateinnamen zurück
; Syntax.........: _gs_dll_SDateiName([$sDateiName = "ADMS"[, $sEndung=".PDF"[, $sDateiPfad = @TempDir[, $vsStartwert="0000"]]]])
; Parameters ....: $sDateiName - Dateiname, Standard "ADMS"
; $sEndung - Dateiendung im .3-Format, Standard ".PDF"
; $sDateiPfad - Dateipfad, Standard @TempDir
; $sStartwert - definiert Zählbeginnn und Länge des seriellen Namensanteils, Standard "0000"
; Return values .: Success - vollständiger Dateienname der Form "C:\temp\ADMS0001.PDF"
; Failure - 0
; Author ........: Tomas Dils
; Modified.......: 12.09.2008
; ===============================================================================================================================
Func _gs_dll_SDateiName($sDateiName = "ADMS", $sEndung = ".PDF", $sDateiPfad = @TempDir, $sStartwert = "0000")
Local $iZahllang = StringLen($sStartwert)
While FileExists($sDateiPfad & "\" & $sDateiName & $sStartwert & $sEndung)
$sStartwert = StringRight("0000000000000000000" & String(Execute($sStartwert + 1)), $iZahllang)
WEnd
Return $sDateiPfad & "\" & $sDateiName & $sStartwert & $sEndung
EndFunc
;ANSI ASCII Übersicht
;http://www.goascii.de/#table2
;===============================================================================
; Name: OemToChar
; Description: Wandelt einen ASCII- in einen ANSI-String
; Parameter(s): $szSrc = String der umgewandelt werden soll
; Requirement(s): keine
; Return Value(s): bei Erfolg: umgewandelter String
; bei Fehler: "" und @error = 1
; Author(s): bernd670
;===============================================================================
Func OemToChar($szSrc)
;~ Private Declare Function OemToChar Lib "user32.dll" Alias "OemToCharA" (ByVal lpszSrc As String, ByVal lpszDst As String) As Long
Local $placeholder
For $i = 0 To StringLen($szSrc)
$placeholder &= " "
Next
Local $lRetVal = DllCall("user32.dll", "long", "OemToChar", "str", $szSrc, "str",$placeholder)
If IsArray($lRetVal) And $lRetVal[0] = 1 Then
Return SetError(0,0,$lRetVal[2])
EndIf
Return SetError(1,0,"")
EndFunc ;==>OemToChar
;===============================================================================
; Name: CharToOEM
; Description: Wandelt einen ANSI- in einen ASCII-String
; Parameter(s): $szSrc = String der umgewandelt werden soll
; Requirement(s): keine
; Return Value(s): bei Erfolg: umgewandelter String
; bei Fehler: "" und @error = 1
; Author(s): Prog@ndy
;===============================================================================
Func CharToOEM($szSrc)
Local $placeholder
For $i = 0 To StringLen($szSrc)
$placeholder &= " "
Next
Local $lRetVal = DllCall("user32.dll", "long", "CharToOem", "str", $szSrc, "str",$placeholder)
If IsArray($lRetVal) And $lRetVal[0] = 1 Then
Return SetError(0,0,$lRetVal[2])
EndIf
Return SetError(1,0,"")
EndFunc ;==>OemToChar
Mit einer speziellen Version von GhostScript , bei der das cFax-Device einbezogen ist, kann man sff-Dateien für Fritz!Fax von AVM erstellen.
PS.: Dank an bernd670 für OemToChar() und Prog@ndy für CharToOEM()