Hier habe ich ein kleines Skript, mit dem man - wie der Threadtitel bereits verrät - Dateien über das Kontextmenü des Explorers drucken kann.
Es macht eigentlich nichts anderes als das bereits vorhandene Drucken/Print. Einziger Gewinn ist, dass man auch bei Ordnern in der Auswahl per Rechtsklick drucken kann. Wenn mindestens ein Ordner unter den markierten Dateien ist, erscheint eine kleine GUI, in der man einstellen kann, wie viele weitere Unterverzeichnisse auch nach druckbaren Dateien durchsucht werden sollen. Null meint keine - also nur die druckbaren Dateien in dem Ordner, eins meint auch die druckbaren Dateien in Verzeichnissen, die in diesem Ordner liegen usw.
Hinweis: Es können nur Dateien gedruckt werden, bei denen auch der normale Windows-Eintrag "Drucken" oder "Print" im Kontextmenü vorhanden ist. Das unterscheidet sich mit der Software, die installiert ist. Ich habe mir nicht die Mühe gemacht, zu schauen wie man das am besten ausliest, sondern meine Konfiguration fest eingetragen. Bei mir ist Office installiert. Daher habe ich in die Liste der druckbaren Dateien etwa doc und xls eingetragen. Je nachdem, was man braucht, gilt es die Zeilen 106 und 110 anzupassen (oder es gleich ordentlich zu machen )
Siehe hierzu vllt. auch einen Diskussions-Thread dazu: Dateien drucken per Explorer Kontextmenü
Das Skript kann solo ohne Installation getestet werden. Einfach Dateien im Explorer markieren und das Skript ausführen.
Das Skript
#AutoIt3Wrapper_UseX64=Y
#AutoIt3Wrapper_Run_After=del /f /q "%scriptdir%\%scriptfile%_stripped.au3"
#AutoIt3Wrapper_Run_Au3Stripper=Y
#Au3Stripper_Parameters=/PE /SF=1 /SV=1 /RM /SCI=1
;~ #pragma compile(Icon, '.\Avosoft-Warm-Toolbar-Print.ico') ; Dieses Icon ist nicht für kommerz. Nutzung frei.
Opt("MustDeclareVars", 1)
#include <WindowsConstants.au3>
#include <Misc.au3>
#include <GUIConstantsEx.au3>
#include <FileConstants.au3> ; Für die Konstanten in _FileListToDict
Global $sName = "Benutzerdefiniertes Drucken"
_Main()
Func _Main()
If _Singleton($sName, 1) = 0 Then Exit ; Bei meheren markierten Dateien, wird das Skript duch das Kontextmenü mehrfach gestartet. Daher Abbruch.
; Zum Auslesen der markierten Dateien aus dem Explorer:
; ; LarsJ - https://www.autoitscript.com/forum/topic/162905-automating-windows-explorer/
Local $hExplorer = WinGetHandle("[REGEXPCLASS:^(Cabinet|Explore)WClass$]")
If Not $hExplorer Then Exit
Local $oShell = ObjCreate("Shell.Application")
For $oWindow In $oShell.Windows()
If $oWindow.HWND() = $hExplorer Then ExitLoop
Next
Local $oPrintItems = ObjCreate("Scripting.Dictionary")
Local $iFolder = 0
For $oItem In $oWindow.Document.SelectedItems() ; Hier ein erster Schleifendurchlauf und Übertrag, um zu checken, ob Ordner markiert sind.
$oPrintItems($oItem.Path()) = True ; Speicherung in ein neues Objekt, damit nicht eventuell während die GUI angezeigt wird, andere Dateien markiert werden können..
If StringInStr(FileGetAttrib($oItem.Path()), "D") Then $iFolder += 1
Next
If $iFolder Then ; Wenn Ordner in Auswahl, dann Frage nach Rekursionstiefe.
Local $iAnswer = _Gui($iFolder)
If $iAnswer = -1 Then Exit MsgBox(64, $sName, "Drucken abgebrochen", 1)
EndIf
Local $iIsPrinted, $sNotPrinted = ""
For $oItem In $oPrintItems.Keys ; Dateien werden in Schleife abgearbeitet.
If StringInStr(FileGetAttrib($oItem), "D") Then
Local $oFiles = _FileListToDict($oItem, True, -1, False, $iAnswer + 1, 1) ; Bei Ordnern wird in angegebener Rekursionstiefe nach weiteren Dateien gesucht und gedruckt.
For $vFiles In $oFiles.Keys
$iIsPrinted = _PrintFile($vFiles)
If Not $iIsPrinted Then $sNotPrinted &= $vFiles & @CRLF ; Falls nicht gedruckt, werden Dateien zur späteren Ausgabe in $sNotPrinted gespeichert.
Next
Else
$iIsPrinted = _PrintFile($oItem)
If Not $iIsPrinted Then $sNotPrinted &= $oItem & @CRLF ; Falls nicht gedruckt, werden Dateien zur späteren Ausgabe in $sNotPrinted gespeichert.
EndIf
Next
If $sNotPrinted <> "" Then ; Falls es Druckfehler gab, werden diese Dateien in MsgBox angezeigt.
$sNotPrinted = "Folgende Dateien wurden nicht gedruckt: " & @CRLF & @CRLF & $sNotPrinted
MsgBox(16, $sName, $sNotPrinted)
EndIf
EndFunc ;==>_Main
Func _Gui($iFolder)
Local $sString = $iFolder & " Verzeichnis"
If $iFolder > 1 Then $sString &= "se"
Local $hGUI = GUICreate($sName, 400, 125, -1, -1, -1, $WS_EX_TOPMOST)
GUISetFont(10, 600, "", "Segoe UI", $hGUI, 5)
Local $idInputBox = GUICtrlCreateInput("0", 72, 48, 55, 25)
GUICtrlCreateUpdown(-1)
GUICtrlSetLimit(-1, 100)
GUICtrlCreateLabel($sString & " ausgewählt. Wie viele weitere evtl.", 5, 5, 390, 20)
GUICtrlCreateLabel("vorhandene Unterverzeichnisse sollen auch gedruckt", 5, 28, 390, 18)
GUICtrlCreateLabel("werden?", 5, 51, 390, 18)
GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
Local $idOK = GUICtrlCreateButton("OK", 100, 95, 100, 25)
Local $idAbort = GUICtrlCreateButton("Abbrechen", 215, 95, 100, 25)
GUISetState()
While 1
Switch GUIGetMsg()
Case $GUI_EVENT_CLOSE, $idAbort
GUIDelete($hGUI)
Return -1
Case $idOK
Local $iAnswer = GUICtrlRead($idInputBox)
GUIDelete($hGUI)
Return $iAnswer
EndSwitch
WEnd
EndFunc ;==>_Gui
Func _PrintFile($sFilePath)
Local $sExtension = StringTrimLeft($sFilePath, StringInStr($sFilePath, '.', 0, -1))
Switch $sExtension
Case "xls", "xlsx", "doc", "docx", "odt", "rtf", "csv" ; Auswahl von Dateien, die in meinem Fall gedruckt werden sollen.
ShellExecuteWait($sFilePath, "", @WorkingDir, "print", @SW_HIDE)
If Not @error Then Return 1
Sleep(50) ; Pause notwendig, weil sonst Fehlermeldungen, wegen gesperrten Dokumenten auftauchen (bei Office-Nutzung). Falls notwendig Pause verlängern.
Case "pdf", "txt"
Return ShellExecute($sFilePath, "", @WorkingDir, "print", @SW_HIDE) ; ShellExecute haut die Druckaufträge einfach raus. Bei ShellExecuteWait bleibt die Reihenfolge erhalten.
Case Else
Return 0
EndSwitch
EndFunc ;==>_PrintFile
;===============================================================================
;
; Function Name: _FileListToDict($vFolder[, $bRec[, $iFileInformation[, $bRelative[, $iMaxDepth[, $iFilesAndOrFolders]]]]])
; Description: Speichert Dateien, optional mit einer gewählten Eigenschaft, in einerm Dictionary-Objekt.
; Parameter(s): $vFolder = Ein Startverzeichnis oder ein eindimensionales Array von Startverzeichnissen für die Dateisuche.
; $bRec = Rekursive Dateisuche bei $bRec = True (Standardwert)
; $iFileInformation = In $oFiles.Items kann eine gewählte Datei-Information gespeichert werden.
; |-1 = Keine Information. $oFiles.Items = True. (Standardwert).
; |0 = Bearbeitungszeitpunkt
; |1 = Erstellzeitpunkt
; |2 = Letzte Zugriffszeit
; |-2 = Dateigröße in bytes
; |-3 = Dateigröße in größter erreichter Einheit.
; $bRelative = $oFiles.Keys haben relativem Dateipfad bei $bRelative = True (Standardwert = False).
; $iMaxDepth = Anzahl der ausgelesenen Unterverzeichnisse unterhalb der/des Startverzeichniss(es) (Standardwert = 100).
; $iFilesAndOrFolders = $oFiles.Keys haben relativem Dateipfad bei $bRelative = True (Standardwert = False).
; |0 = Dateien und Ordner
; |1 = Nur Dateien
; |2 = Nur Ordner
; Return Value(s): Zurückgegeben wird ein Objekt mit den kompletten oder relativen Dateipfaden als Key (abhängig von $bRelative)
; und in Abhängigkeit von $iFileInformation mit True oder Datei-Information als Item.
;
; @error kann folgende Werte annehmen (Kombinationen möglich, BitOr):
; 0 = kein Fehler aufgetreten, alle Dateien wurden korrekt kopiert
; 1 = Der übergebene Pfad ist kein existierendes Verzeichnis
; 2 = Startverzeichnis-Array ist nicht eindimensional
; Author(s): autoiter
; Modified:
; Remarks:
;===============================================================================
Func _FileListToDict($vFolder, $bRec = True, $iFileInformation = -1, $bRelative = False, $iMaxDepth = 100, $iFilesOrFolders = 0)
If $iFileInformation <> -1 Then
Switch $iFileInformation
Case 0
$iFileInformation = $FT_MODIFIED
Case 1
$iFileInformation = $FT_CREATED
Case 2
$iFileInformation = $FT_ACCESSED
Case -2, -3 ; FileGetSize
Case Else
$iFileInformation = -1
EndSwitch
EndIf
If $bRec Then
If $iMaxDepth < 1 Or Int($iMaxDepth) = 0 Then $iMaxDepth = 1
EndIf
If IsArray($vFolder) Then
If UBound($vFolder, 2) > 1 Then Return SetError(2)
Local $iMaxIndex = UBound($vFolder)
Local $aFolder[$iMaxIndex], $iCount = 0
For $i = 0 To $iMaxIndex - 1
If Not StringInStr(FileGetAttrib($vFolder[$i]), "D") Then ContinueLoop
$aFolder[$iCount] = $vFolder[$i]
$iCount += 1
Next
If $iCount = 0 Then Return SetError(1)
$iMaxIndex = $iCount
ReDim $aFolder[$iMaxIndex]
Else
Local $iMaxIndex = 1
Local $aFolder[$iMaxIndex]
If Not StringInStr(FileGetAttrib($vFolder), "D") Then Return SetError(1)
$aFolder[0] = $vFolder
EndIf
Local $oFiles = ObjCreate("Scripting.Dictionary")
Local $aSearchFile[256], $sFile, $iDepth, $iInfo, $sFolder, $sStartFolder
For $i = 0 To $iMaxIndex - 1
$iDepth = 1
$sFolder = StringRegExpReplace($aFolder[$i], "\\$", "")
$sStartFolder = $sFolder ; Startfolder wird zur Bildung des vollen Dateipfades gespeichert.
$aSearchFile[$iDepth] = FileFindFirstFile($sFolder & "\*")
While $iDepth >= 0 ; In dieser Schleife werden alle Dateien/Ordner abgehandelt
$sFile = FileFindNextFile($aSearchFile[$iDepth])
If @extended And $bRec And $iDepth < $iMaxDepth Then ; Wenn es sich um ein Ordner handelt wird in diesem weiter gesucht - solange max. Rekursionstiefe nicht erreicht.
$iDepth += 1
$sFolder &= "\" & $sFile
If $iFilesOrFolders <> 1 Then $oFiles($sFolder) = $iInfo
$aSearchFile[$iDepth] = FileFindFirstFile($sFolder & "\*")
ElseIf @error Then ; Wenn keine Dateien mehr im Ordner vorhanden sind wird das "Handle" Freigegeben
FileClose($aSearchFile[$iDepth])
$iDepth -= 1
$sFolder = StringRegExpReplace($sFolder, "\\[^\\]*$", "")
Else
If $iFilesOrFolders <> 0 Then
If $iFilesOrFolders = 1 And StringInStr(FileGetAttrib($sFolder & "\" & $sFile), "D") Then ContinueLoop
If $iFilesOrFolders = 2 And Not StringInStr(FileGetAttrib($sFolder & "\" & $sFile), "D") Then ContinueLoop
EndIf
If $iFileInformation <> -1 Then
$iInfo = ""
Switch $iFileInformation
Case 0, 1, 2
$iInfo = FileGetTime($sFolder & "\" & $sFile, $iFileInformation, $FT_STRING)
Case -2
If Not StringInStr(FileGetAttrib($sFolder & "\" & $sFile), "D") Then $iInfo = FileGetSize($sFolder & "\" & $sFile)
Case -3
If Not StringInStr(FileGetAttrib($sFolder & "\" & $sFile), "D") Then $iInfo = __FileListToDict_ByteSuffix(FileGetSize($sFolder & "\" & $sFile))
EndSwitch
If @error Then ContinueLoop
If Not $bRelative Then
$oFiles($sFolder & "\" & $sFile) = $iInfo
Else
$oFiles(StringReplace($sFolder, $sStartFolder, "") & "\" & $sFile) = $iInfo
EndIf
Else
If Not $bRelative Then
$oFiles($sFolder & "\" & $sFile) = True
Else
$oFiles(StringReplace($sFolder, $sStartFolder, "") & "\" & $sFile) = True
EndIf
EndIf
EndIf
WEnd
Next
Return SetError(0, $oFiles.Count, $oFiles)
EndFunc ;==>_FileListToDict
Func __FileListToDict_ByteSuffix($iBytes) ; Aus der Hilfe zu FileGetSize.
Local $iIndex = 0, $aArray = [' bytes', ' KB', ' MB', ' GB', ' TB', ' PB', ' EB', ' ZB', ' YB']
While $iBytes > 1023
$iIndex += 1
$iBytes /= 1024
WEnd
Return Round($iBytes) & $aArray[$iIndex]
EndFunc ;==>__FileListToDict_ByteSuffix
Alles anzeigen
Installation in Kontextmenü
Hier ein Skript zum Installieren in das Kontextmenü (muss im Skriptverzeichnis liegen. Skript muss kompiliert im Verzeichnis vorhanden sein - kann man natürlich auch alles ändern..)
#RequireAdmin
Global $sName = "Benutzerdefiniertes Drucken"
Global $bError = False
RegWrite("HKEY_CLASSES_ROOT\*\shell\" & $sName)
If @error Then $bError = True
RegWrite("HKEY_CLASSES_ROOT\*\shell\" & $sName, "", "REG_SZ", $sName)
If @error Then $bError = True
RegWrite("HKEY_CLASSES_ROOT\*\shell\" & $sName, "Icon", "REG_SZ", '"' & @ScriptDir & '\' & $sName & '.exe"')
If @error Then $bError = True
RegWrite("HKEY_CLASSES_ROOT\*\shell\" & $sName & "\command")
If @error Then $bError = True
RegWrite("HKEY_CLASSES_ROOT\*\shell\" & $sName & "\command", "", "REG_SZ", '"' & @ScriptDir & '\' & $sName & '.exe"')
If @error Then $bError = True
RegWrite("HKEY_CLASSES_ROOT\Folder\shell\" & $sName)
If @error Then $bError = True
RegWrite("HKEY_CLASSES_ROOT\Folder\shell\" & $sName, "", "REG_SZ", $sName)
If @error Then $bError = True
RegWrite("HKEY_CLASSES_ROOT\Folder\shell\" & $sName, "Icon", "REG_SZ", '"' & @ScriptDir & '\' & $sName & '.exe"')
If @error Then $bError = True
RegWrite("HKEY_CLASSES_ROOT\Folder\shell\" & $sName & "\command")
If @error Then $bError = True
RegWrite("HKEY_CLASSES_ROOT\Folder\shell\" & $sName & "\command", "", "REG_SZ", '"' & @ScriptDir & '\' & $sName & '.exe"')
If @error Then $bError = True
If $bError Then
RegDelete("HKEY_CLASSES_ROOT\*\shell\" & $sName)
RegDelete("HKEY_CLASSES_ROOT\Folder\shell\" & $sName)
Exit MsgBox(16, $sName, "Fehler beim Installieren. Keine Änderungen vorgenommen.")
EndIf
MsgBox(64, $sName, "Installation abgeschlossen.")
Alles anzeigen
Deinstallation aus dem Kontextmenü
#RequireAdmin
Global $sName = "Benutzerdefiniertes Drucken"
Global $bNothing = False
Global $iError = 0
$iTest = RegDelete("HKEY_CLASSES_ROOT\*\shell\" & $sName)
$iError = @error
If $iTest = 0 And $iError = 1 Then $bNothing = True
RegDelete("HKEY_CLASSES_ROOT\Folder\shell\" & $sName)
$iError = @error
If $iTest = 0 And $iError = 1 Then
If $bNothing Then Exit MsgBox(64, $sName, "Ein Fehler ist aufgetreten. Programm ist nicht installiert.")
EndIf
If $iError <> 0 Then
MsgBox(16, $sName, "Ein Fehler ist aufgetreten. Deinstallation nicht möglich.")
Else
MsgBox(64, $sName, "Deinstallation erfolgreich.")
EndIf
Alles anzeigen
Im Anhang nochmal die Skripte zusammen mit einem Icon.
EDIT: Das Skript wurde nach Beitrag 2 nochmal leicht bearbeitet. Zwar ohne sichtbaren Effekt, aber nun ohne Fehler.