marc-olivier-jodoin-0TB3AiOu2g4-unsplash

Kürzlich fragte mich Blogbesucher Sebastian nach Hilfe: Mittels Batch-Skript sollen innerhalb eines Ordners, in einer bestimmten Unterordnertiefe, bestimmte Ordner umbenannt werden. In dem Artikel des Kommentars hatte ich Hilfestellung gegeben, bestimmte Aktionen auf alle Unterordner eines Ordners auszuführen. Die Einschränkung, diese Aktionen nur auf ein bestimmten Level von Unterordnern auszuführen, gab es nicht. Schauen wir uns das mal an.

Auslesen von tiefen Ordnerstrukturen

Die Grundstruktur bleibt erstmal gleich: Mit for /d in ([order]\*) do () werden Befehle auf alle Unterordner eines Ordners ausgeführt. Mit dem zusätzlichen Parameter /r durchsuchen wir rekursiv tiefe Ordnerstrukturen und ignorieren sogar Dateien für mehr Performance.

batch-deep-recursion-folder-manipulation-tiefe-ordnerstrukturen-bearbeiten-ausgabe
Mit for /d /r tiefe Ordnerstrukturen durchlaufen und ausgeben

Der Befehl wird dann leicht umgebaut: for /d /r "[ordner]" %%i in (*) do ()
Dann noch etwas Ausgabe mit dazu und wir haben fast den tree Befehl nachgebaut 😉

@echo off
setlocal enableDelayedExpansion 

for /d /r "%cd%" %%i in (*) do (
	echo %%i
)
pause
endlocal

Erkennung der Tiefe des aktuellen Ordners

Jetzt brauchen wir eine Erkennung der Tiefe. Das hat mich etwas länger beschäftigt als gedacht.
An die Tiefe der Rekursion von for /d /r scheint man leider nicht zu kommen und mehrere nicht-rekursive for-Schleifen ineinanderschachteln ist zu unflexibel. Stattdessen war folgender späterer Gedanke attraktiv einfach: Die Backslashes im Ordnerpfad zählen und damit die Tiefe erkennen.
Etwas sehr simpel aber das einzige, das ich erfolgreich umsetzen konnte. Wer hier einen besseren Ansatz hat, gerne ein Kommentar hinterlassen.

Das Zählen von Zeichen in einem String ist in Batch leider kein Einzeiler, aber das Rad muss ja nicht neu erfunden werden. Hier hat schonmal jemand eine Funktion dafür geschrieben. Möglich wäre auch die Nutzung von Powershell mit dem [string].split() Befehl, jedoch ist die Nutzung von Powershell in Batch ein Fass, dass wir hier jetzt nicht öffnen.

Nun zählen wir für jeden Unterordner die Backslashes, subtrahieren die Anzahl der Backslashes des Ordners, in dem das Skript ausgeführt wird und erhalten damit die relative Tiefe zum Skriptordner.

@echo off
setlocal enableDelayedExpansion 

set startdir=%cd%

call :GetCharCount startLevel %startdir% \

for /d /r "%cd%" %%i in (*) do (
	echo %%i
	call :GetCharCount level %%i \
	echo absolute Tiefe: !level!
	set /a relLevel=!level!-!startLevel!
	echo relative Tiefe: !relLevel!
)
pause
endlocal

:GetCharCount
  set _S=%~2
  set /a %~1 = 0
  for /L %%i in (0,1,10000) do (
    if "!_S:~%%i,1!"=="" (set "_S=" & exit /b)
    if /i "!_S:~%%i,1!"=="%~3" set /a %~1 += 1
  )
  set "_S="
  exit /b
batch-deep-recursion-folder-manipulation-tiefe-ordnerstrukturen-bearbeiten-tiefe-ausgeben
Absolute und relative Tiefe zum Skriptordner errechnen und ausgeben.

Verarbeitung von Ordnern in Abhängigkeit von Bedingungen

So, nun kann die Logik in Abhängigkeit von der Tiefe und weiteren gewünschten Faktoren mit ifs verbaut werden.
Alle Ordner in der Tiefe X UND mit dem Ordnernamen Y sollen umbenannt werden? Ich habe das beispielhaft (mit viel debug output) mal umgesetzt:

@echo off
setlocal enableDelayedExpansion 

set startdir=%cd%
set renameFrom=BitteUmbenennen
set renameTo=NeuerOrdnername
call :GetCharCount startLevel %startdir% \

for /d /r "%cd%" %%i in (*) do (
	echo ----
	echo %%i
	call :GetCharCount curLevel %%i \
	set /a relLevel=!curLevel!-!startLevel!
	for %%J in (%%i) do set foldername=%%~nxJ
	echo absolute Tiefe: !curLevel!
	echo relative Tiefe: !relLevel!
	echo Ordnername: !foldername!
	if !relLevel!==3 if "!foldername!"=="!renameFrom!" (
		echo **** RENAME ****
		set oldPath=%%i
		set newPath=!oldPath:%renameFrom%=%renameTo%!
		echo !newPath!
		move !oldPath! !newPath!
		echo ****
	)
)
pause
endlocal

:GetCharCount
  set _S=%~2
  set /a %~1 = 0
  for /L %%i in (0,1,10000) do (
    if "!_S:~%%i,1!"=="" (set "_S=" & exit /b)
    if /i "!_S:~%%i,1!"=="%~3" set /a %~1 += 1
  )
  set "_S="
  exit /b
batch-deep-recursion-folder-manipulation-tiefe-ordnerstrukturen-bearbeiten-umbenennen
Tiefe Ordnerstrukturen werden durchsucht und (beispielhaft) abhängig von der Tiefe und dem Ordnernamen umbenannt

Das ist jetzt natürlich beliebig erweiterbar aber das Prinzip sollte klar werden. Mehrere Voraussetzungen können einfach durch aneinanderreihen von ifs geprüft werden, quasi eine Einzeiler-Verschachtelung. Den aktuellen Ordnernamen ziehen wir mittels for-Befehl raus. Den neuen Ordnernamen bauen wir dank Batch String Manipulation. Das wäre in Powershell vermutlich ein Fünfzeiler aber sowas sieht in Batch irgendwie immernoch „schön“ aus 😉

Finale Version mit mehr Funktionen

Ich habe es vielleicht etwas übertrieben aber ich finde es immernoch interessant und unterhaltsam, in Batch zu coden, auch wenn es super umständlich ist und mit jeder Programmiersprache vermutlich einfacher wäre. Die finale Version beinhaltet weitere Möglichkeiten:

  • Steuerung des Tools mittels Parameter statt fest in den Code eingetragene Variablen – somit ließe sich das Ganze auch in eine .exe verwandeln und flexibel einsetzen. Optionale Modi (siehe unten), Ordnertiefe, Ziel und beliebig viele Quellordner könnt ihr beim Aufruf mit übergeben. Wenn das Programm ohne Parameter gestartet wird, wird eine Hilfe zur Nutzung ausgegeben.
  • Die Angabe mehrerer Quellordnernamen, die in einem Zielordner vereint werden sollen – die Dateien aller dieser Ordner werden im Zielordner derselben Ebene gesammelt.
  • Test-Modus zum Ausprobieren der Einstellungen. Im Testmodus geschieht alles so wie im Normaldurchlauf, nur dass die tatsächliche Datenverarbeitung übersprungen wird. Eine Ausgabe, wo sonst eine Dateiaktion passiert wäre, gibt es trotzdem.
  • Verbose- und Silent-Modus für viel oder wenig Ausgaben während der Abarbeitung. Im Silent-Modus gibt es nur 1 Ausgabe je Ordner, der umbenannt wird. Im Verbose Modus habt ihr viel zu Scrollen! 😉

Der Quelltext hier hier einsehbar: Code anzeigen

@ECHO off
SETlocal enableDelayedExpansion 

REM Author: Hannes Schurig
REM Date: 02.09.2019
REM More: https://it-stack.de/05/08/2019/tiefe-ordnerstrukturen-untersuchen-und-verarbeiten-mit-batch-2019

SET startdir=%cd%

IF "%1"=="" (
	ECHO ## USAGE ##
	ECHO.
	ECHO thistool.bat [--test] [--verbose] [depth] [renameTo] [renameFrom]
	ECHO test [optional]: Use "--test" to run in test mode. Normal outputs but no rename will actually be triggered.
	ECHO verbose [optional]: Use "--verbose" to get lots of output, without this there will be just one output per rename done.
	ECHO depth: In which folder level [relative to this tool] will rename do its work?
	ECHO renameTo: Folder name to rename to.
	ECHO renameFrom: As many folder names as you want that will get renamed. Foldernames with spaces in double quotes.
	ECHO.
	ECHO ## Exemplary ##
	ECHO.
	ECHO thistool.bar --test 3 newName "old Name 1" oldName2
	ECHO would run this tool in test-mode [no renames will be done] and both folders "old Name 1" [without quotes]
	ECHO and oldName2 in folder level 3 below this tools folder will trigger the rename process.
	ECHO thistool.bat --verbose 4 "new folder" "old Name" anotherFolder
	ECHO This will actually rename anotherFolder and "old Name" to "new folder" [both without quotes] in 4-level-deep subfolders 
	ECHO and output lots of stuff.
	PAUSE
	ENDLOCAL
	EXIT /B
)

:OptionalParams
REM number detection from: https://stackoverflow.com/a/17585404
ECHO(%~1|findstr "^[-][1-9][0-9]*$ ^[1-9][0-9]*$ ^0$">nul && GOTO :RequiredParams
IF "%1"=="--test" SET test=test&&SHIFT
IF "%1"=="--verbose" SET verbose=verbose&&SHIFT
GOTO :OptionalParams

:RequiredParams
SET depth=%1
SHIFT
SET renameTo=%1

SET "renameFrom=%*"
SET "renameFrom=!renameFrom:*%1 =!"
GOTO :LetsGo

:LetsGo
CALL :GetCharCount startLevel %startdir% \
IF "!verbose!"=="verbose" (
	ECHO ##############################
	ECHO verbose: !verbose!
	ECHO test: !test!
	ECHO depth: !depth!
	ECHO renameTo: !renameTo!
	ECHO renameFrom: %renameFrom%
	ECHO startdir: !startdir!
	ECHO level of startdir: !startlevel!
	ECHO ##############################
)

pause

FOR /d /r "%cd%" %%A IN (*) DO (
	CALL :GetCharCount curLevel "%%A" \
	SET /a relLevel=!curLevel!-!startLevel!
	FOR %%B IN ("%%A") DO SET "foldername=%%~nxB"
	IF "!verbose!"=="verbose" (
		ECHO ----
		ECHO %%A
		ECHO absolute Tiefe: !curLevel!
		ECHO relative Tiefe: !relLevel!
		ECHO Ordnername: !foldername!
	)
	IF !relLevel!==!depth! (
		FOR %%C IN (%renameFrom%) DO (
			SET tempRenameFrom=%%C
			SET cleanFolderName=!tempRenameFrom:"=!
			IF "!foldername!"=="!cleanFolderName!" (
				CALL :RenameFolder %%C "%%A"
			)
		)
	)
)

pause
endlocal
EXIT /B

:RenameFolder
	SET renameFromActual=%~1
	SET oldPath=%~2
	SET cleanRenameTo=!renameTo:"=!
	SET newPath=!oldPath:%renameFromActual%=%cleanRenameTo%!
	IF "!verbose!"=="verbose" (
		ECHO **** RENAME ****
		ECHO From: !oldPath!
		ECHO To: !newPath!
	) ELSE (
		ECHO *** Ordner !oldPath! wird umbenannt!
	)
	IF NOT "!test!"=="test" (
		IF NOT EXIST "!newPath!" (
			move "!oldPath!" "!newPath!">nul
		) ELSE (
			COPY /Y "!oldPath!" "!newPath!">nul
			RD /S /Q "!oldPath!">nul
		)
	) ELSE (
		ECHO Test-Modus aktiv, !oldPath! wird nicht umbenannt.
	)
	ECHO.
	EXIT /B

:GetCharCount
	SET _S=%~2
	SET /a %~1 = 0
	FOR /L %%i IN (0,1,10000) DO (
	IF "!_S:~%%i,1!"=="" (SET "_S=" & exit /b)
	IF /i "!_S:~%%i,1!"=="%~3" SET /a %~1 += 1
	)
	SET "_S="
	EXIT /B

Nutzung des Skripts

Das Skript wird über Paramter beim Aufruf gesteuert:

rename.bat [--test] [--verbose] [depth] [renameTo] [renameFrom]

### Was machen die Parameter? ###
--test: Startet den Testmodus des Tools. Es läuft normal durch, gibt normale Ausgaben aber der Umbenennungs-Befehl wird nicht ausgeführt. Gut zum Testen.
--verbose: Mit dem --verbose Parameter werden viele hilfreiche Ausgaben während der Ausführung gemacht. Ohne diesen Parameter gibt das Tool ausschließlich 1 Zeile pro erfolgter Umbenennung aus, nicht mehr.
depth: In welcher Ordnertiefe werden die Ordner geprüft und umbenannt?
renameTo: Neuer Ordnername
renameFrom: Beliebig viele alte Ordnernamen, die umbenannt werden sollen

### Beispielhafte Aufrufe ###
rename.bat --test 3 NeuerName AlterName1 "Alter Name 2"
rename.bat --test --verbose 4 "Neuer Ordner" "Alter Ordner" Testordner
usw.

@Sebastian: Ich hoffe, deine Anfrage ist damit erfolgreich beantwortet und du kannst den Code so für deine Zwecke einsetzen. Sag Bescheid, wenn du noch Hilfe brauchst.

Das Installieren von .NET-Framework 3.5 war unter Windows 7 noch relativ einfach – Online- oder Offline-Installer herunterladen und los! Unter Windows 10 kann das unter Umständen mehr Probleme machen. Die Fehlercodes 0x800F081F und 0x800F0906 können die Installation bzw. Aktivierung sehr umständlich machen. „Aktivierung“, da das .NET-Framework 3.5 bereits in der Feature-Liste von Windows 10 („Windows-Features aktivieren oder deaktivieren“ im Startmenü) gelistet wird und eigentlich nur per Häkchen aktiviert werden muss. Windows 10 lädt das dann über Windows Update nach. Im besten Fall. Oder beim Nachladen der Installationsdaten von Windows Update erscheinen die besagten Fehlermeldungen.

Die Installation erfolgt nun über ein Installationsmedium von Windows 10 – via USB oder ISO. Beides lässt sich binnen Sekunden über das Windows 10 Media Creation Tool herunterladen bzw. erstellen. Ich empfehle das ISO-Abbild, dieses lässt sich mit Rechtsklick -> Bereitstellen direkt in ein virtuelles Laufwerk verwandeln.

Nun braucht es für die Installation nur noch ein paar Befehle aus der administrativen CMD (als Admin starten!): 

del /q C:\Windows\SoftwareDistribution\Download
Dism /Online /Cleanup-Image /StartComponentCleanup
DISM /Online /Enable-Feature /FeatureName:NetFx3 /All /LimitAccess /Source:D:\sources\sxs

Neustart, fertig!
via

Mit einem einfachen „Trick“ könnt ihr die wiederkehrende Tipparbeit in der Windows Kommandozeile vereinfachen: Aliase.
Gemeint sind selbst definierte (zumeist kurze oder einfache) Befehle, die andere (zumeist lange oder komplexe) Befehle ersetzen oder mehrere Befehle kombinieren.

Ein paar Beispiele, welche komplexeren Befehle durch einen einfachen Alias ersetzt werden könnten:

:ausführlichen IP-Config-Bericht in die Zwischenablage
ipconfig /all | clip
: Einfacher Netzwerkreset
ipconfig /flushdns && ipconfig /release && ipconfig /renew
: WLAN-Passwort von einem WLAN anzeigen
netsh wlan show profile [WLAN-Name] key=clear
: Git Branch aktualisieren, Pakete installieren, lokale Variable setzen und Node starten
git pull && npm i && set envtype=localtest && npm run debug

Aliase erstellen

windows-cmd-aliase-befehle-commands-path

Erstellt zuerst einen neuen Ordner, irgendwo auf eurem PC und kopiert euch den Pfad dorthin, z.B.: C:/aliase

Öffnet Erweiterten Systemeinstellungen (Start -> Erweiterte Systemeinstellungen oder Ausführen -> sysdm.cpl) -> Erweitert -> Umgebungsvariablen und fügt dort diesen Pfad im oberen und unteren Teil jeweils zu Path hinzu:

Dies bewirkt, dass alle Inhalte dieses Ordners jederzeit über die Kommandozeile aufgerufen werden können, also global aufrufbar sind.
Startet alle offenen CMD-Fenster danach neu, sonst kommt die Änderung nicht an.

Anschließend erstellt ihr euch in dem Ordner Dateien mit einem Dateinamen nach Format: [Befehl].bat – mit dem gewünschten Befehl/Alias. Beispielsweise: ipr.bat (Eselsbrücke „IP-Reset“)
Öffnet die Datei in einem Texteditor und fügt ein:

REM ipr.bat:
@echo off
echo Run: ipconfig /flushdns + /release + /renew
ipconfig /flushdns && ipconfig /release && ipconfig /renew

oder pir.bat („pull-install-restart“):

REM pir.bat:
@echo off
echo Run: git pull + npm i + npm run debug
git pull && npm i && npm run debug

REM und echo sind optional und dienen nur zur Info. Nachdem ihr die Datei gespeichert habt, lässt sie sich per Doppelklick starten und per CMD wie ein Befehl aufrufen:

Aliase mit Parametern

Ein weiterer Punkt kann noch wichtig sein: Wenn ihr dynamische Informationen (Parameter) an das Skript hinter dem Alias geben müsst. Beispielsweise braucht das Auslesen des WLAN-Schlüssels den WLAN-Namen (SSID) dafür oder der Ping brauch ein Pingziel.
Parameter lassen sich in Batch Skripte entweder per %1 … %9 (1. bis 9. Parameter) oder %* (alle angegebenen Parameter nacheinander) übergeben. Folgende Beispiele sind nicht besonders sinnvoll und sollen nur der Demonstration dienen:

REM rf.bat:
@echo off
echo unveil + delete %*
attrib -r -a -s -h %*&&del /f /q %*
REM p.bat:
@echo off
echo Usage: p [target] [count] [version]
echo ping %1 -n %2 -%3
ping %1 -n %2 -%3

Ein kleiner Aufwand für dich, aber eine große Erleichterung für deine Finger! 😉
Ich verwende Aliase, da ich als Programmierer im Alltag einige Befehle dutzende Male pro Tag ausführen muss.

Bei Kinder- bzw. Jugendschutzprogrammen ist es eine sehr wichtige Funktion: Das Starten einzelner Programme verhindern oder nur bestimmte Programme zulassen und alle anderen blockieren. Das lässt sich händisch jedoch auch ohne eingekaufte Zusatzsoftware in wenigen Minuten einrichten:

Mit der Registry nur bestimmte Programme zulassen

Sucht in der Registry nach dem Schlüssel:

HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies

Ihr erstellt nun einen Schlüssel „Explorer“ unter „Policies“ und einen DWORD-Wert „RestrictRun“ mit Wert „1“. In „Explorer“ erstellt ihr dann noch einen neuen Schlüssel „RestrictRun“ und könnt hier nun beliebig viele Zeichenfolgen erstellen. Jede Zeichenfolge steht für ein erlaubtes Programm. Alle Programme, die hier jetzt nicht gelistet sind, dürfen auch nicht mehr gestartet werden*. 
Der Name der Zeichenfolge ist eine fortlaufende Nummerierung und als Wert wird der Dateiname des Programms gesetzt. Die Änderungen werden beim Ab- und wieder Anmelden bzw. Neustart für den Nutzer aktiv. 

Einstellungen unter HKEY_CURRENT_USER gelten nur für den gerade angemeldeten Nutzer. Daher muss der Vorgang für jeden Nutzer, der eingeschränkt werden soll, innerhalb dessen Anmeldung gemacht werden. Oder ein Admin setzt die Einstellungen via HKEY_USERS, mehr dazu im letzten Abschnitt. 

Zum Testen empfehle ich, regedit.exe mit einzutragen. Somit könnt ihr auch in dem eingeschränkten Benutzer die Einstellungen noch via regedit.exe anpassen. Für den finalen Einsatz sollte regedit.exe unbedingt nicht erlaubt sein (also nicht auf der Liste stehen), weil der Nutzer sonst die Einstellung aushebeln könnte.

*RestrictRun blockiert nur Programmstarts über den Nutzerkontext des eingeschränkten Nutzers. Heißt: Systemkomponenten, Dienste oder Programme, die über einen anderen Nutzerkontext geladen werden, wie die CMD oder der Taskmanager, werden nicht blockiert. Das ist ganz gut, damit Treiber, Sicherheitsprogramme und andere kritische Windows-Komponenten weiterhin funktionieren. Prüft vorher das eingeschränkte Konto auf die gewünschten Einschränkungen.

Woher bekomme ich die Dateinamen meiner Programme?

Das ist relativ einfach, zwei Wege kurz beschrieben:

  1. Rechtsklick auf jede Verknüpfung, beispielsweise auf dem Desktop oder im Startmenü -> Eigenschaften und dort steht am Ende von „Ziel“ die ausführende Datei.
  2. Während das Programm geöffnet ist im Tastkmanager Rechtsklick darauf -> Eigenschaften und dann steht der Dateiname neben dem Programmicon. Eventuell müsst ihr den Programmlistenpunkt aufklappen und die Dateinamen der Unterpunkte somit auslesen, sollten es mehrere sein.

Via Registry bestimmte Programme blockieren

Das Blockieren einzelner Programme funktioniert nun fast genauso. In „Explorer“ wird nun ein Schlüssel und ein DWORD-Wert namens „DisallowRun“ erstellt. Im Schlüssel dient wieder eine Liste von Zeichenfolgen für die Aufzählung von Programmen bzw. deren ausführbaren Dateien. Die in der Liste eingetragenen Programme dürfen nicht mehr gestartet werden, alle anderen sind noch erlaubt.

  1. regedit.exe, SystemSettings.exe, SystemPropertiesAdvanced.exe, mmc.exe und weitere Systemtools solltet ihr vielleicht sperren. Vor allem, wenn ihr dem eingeschränkten Nutzer zutraut, euren Schutz umgehen zu wollen.
  2. Die Einstellungen setzt ihr beim ersten Login noch über die regedit.exe, ab dem zweiten Login werden Änderungen dann aber via Adminkonto gesetzt, da ja regedit.exe nicht mehr zugelassen sein sollte. Siehe letztes Kapitel.

Administration der Einstellungen außerhalb des eingeschränkten Nutzers

Ist ein Nutzer erst einmal eingeschränkt, wird die Administration schwierig. Wenn nur bestimmte Programme zugelassen sind, regedit.exe jedoch nicht, lässt sich nicht so einfach etwas ändern.
Hier empfiehlt es sich, die Einstellungen vor dem Login dieses Nutzers durch einen anderen Nutzer (mit Administrationsrechten) anzupassen.

Die benutzerspezifischen Inhalte des HKEY_CURRENT_USER können auch über einen anderen Nutzer via HKEY_USERS/[SID] eingesehen und geändert werden. Die SID des gewünschten Nutzers kann über die CMD ausgelesen werden:

REM// aktuell angemeldeter Nutzer:
C:\Users\Hannes>wmic useraccount where name='%username%' get sid
REM// SID
REM// S-1-5-21-3483483838-1959189235-3432330904-1001

REM// beliebiger Nutzername
C:\Users\Hannes>wmic useraccount where name='Hannes' get sid
REM// SID
REM// S-1-5-21-3483483838-1959189235-3432330904-1001

Mit dieser SID könnt ihr dann aus jedem Adminaccount heraus die Registry und den RestrictRun / DisallowRun Eintrag des Nutzers anpassen. Einfach die gewünschten Programme eintragen, als Nutzer anmelden, diese nutzen. So lassen sich die Einstellungen übrigens auch in Masse aus einem Account heraus einstellen und der Prozess auch einfach per Skript automatisieren und auf beliebig viele Nutzer ausrollen.

windows-restrictrun-start-whitelist-einrichten-sid-hkey-users
Über die CMD die SID eines Nutzers auslesen und seine Registry anpassen

beliebig-viele-pdf-dateien-auf-einmal-drucken-unsplash-teaser

Das Drucken vieler Dokumente auf einmal klingt simpel, hat im Detail jedoch kleine Tücken. Windows bietet bei mehreren markierte Dateien im Kontextmenü „Drucken“ an, jedoch Vorsicht: Je nach Dateityp und Anzahl der Dateien steht diese Option vielleicht nicht zur Verfügung.

Empfehlung: Software mit vielen Features

Ich war selber überrascht, wie anstrengend es ist, nur mit Windows Boardmitteln viele Dateien auf einmal zu drucken. Fazit: Maximal 15 Dateien eines Dateityp desselben Ordners … sehr limitierte Möglichkeiten. Am besten greift man hier zu Software, mit der das kein Problem mehr ist. Wer das nicht möchte oder keine Installationsrechte hat, kann die folgenden Überschriften für die manuellen Vorgehensweisen lesen.

Ich empfehle an dieser Stelle die Freeware Print Conductor. Diese hat eine besonders einfache Oberfläche, unterstützt über 75 Dateiformate und druckt mit nur 3 Klicks alle gewünschten Dateien aus. Das Tool kann jedoch noch viel mehr: Import/Export von Drucklisten, Druckeinstellungen für jedes Dokument unterschiedlich, Druckeinstellungen in einer .ini Datei und somit übertragbar, Deckblätter, Schätzen der Seitenanzahl, Druck-Berichte – hier bleiben keine Wünsche offen.

beliebig-viele-dokumente-auf-einmal-drucken-print-conductor-freeware
Freeware Print Conductor druckt einfach viele Dokumente auf einmal

Müsst ihr das Drucken von Dokumenten im sehr großen Stil fahren oder gar komplex automatisieren? Dann hilft vielleicht auch 2Printer, ein Kommandozeilentool mit ähnlichen Möglichkeiten. Zwei weitere Artikel meines Blogs zum Thema Drucker in Kommandozeilen hier.

Wie es komplett ohne Helfertools geht? Im Folgenden erläutert für PDF, Word, Excel und Bilder.

Manuell: Mehrere PDFs drucken

Bei PDF-Dokumenten werden alle markierten Dateien auf dem Standarddrucker mit den Standardeinstellungen gedruckt. Weitere Druck-Dialoge oder Druck-Anpassungen vorher sind nicht möglich, der Druck erfolgt sofort. Zusätzlich funktioniert das nur bis maximal 15 selektierten PDFs in einem Ordner, ab 16 markierten Dateien verschindet die Option. Beide Probleme lassen sich aber mit derselben Methode umgehen.

beliebig-viele-pdf-dateien-auf-einmal-drucken-pdf-explorer
Explorer Rechtsklick-Kontextmenü bei 15 und 16 markierten PDFs

Lösung bei PDFs: Hier hilft nur das Zusammenfügen aller Dokumente zu einer einzigen PDF, um diese dann zu drucken. Somit lassen sich beliebig viele PDFs auf einmal mit der Möglichkeit der Druck-Anpassung vorher drucken. Das ist glücklicherweise mit Tools wie der Freeware PDFsam Basic sehr einfach zu bewerkstelligen. So geht es: Einfach im „Zusammenführen“ Modus alle gewünschten PDFs in das Fenster ziehen, Zielordner wählen, „Start“ drücken und fertig. Noch einfacher: Dateien markieren -> Rechtsklick -> Senden an -> PDFsam Basic -> Zusammenführen.

mehrere-beliebig-viele-pdf-dokumente-auf-einmal-drucken-pdfsam
PDFs zusammenführen mit PDFsam

Andere Dateitypen drucken

Bei Office-Dokumenten verhält es sich ähnlich: Bis zu 15 Dokumente desselben Dateityps (z.B. xlsx) im selben Ordner lassen sich über das Kontextmenü jeweils drucken, ab 16 verschwindet die Option. Hier müssen die Dateien wieder kombiniert werden, in Word über Einfügen -> Objekt -> Text von Datei. Excel kann manuell über Daten -> Daten abrufen -> Aus Datei mehrere Dokumente z.B. in seperate Tabellenblätter laden, alternativ gibt es Makros und Skripts für das automatische Mergen vielen Excel-Dateien. Wirklich nutzerfreundlich ist das alles nicht, aber letztlich funktioniert es.

Einfacher ist es dagegen bei Bilddateien unterschiedlicher Dateitypen. Diese können über das Kontextmenü gedruckt werden, selbst wenn mehr als 15 Dateien unterschiedlicher Bildformate ausgewählt wurden. Außerdem erscheint vor dem Druck ein eigener Dialog, der es ermöglicht, Druckeinstellungen anzupassen und z.B. Collagen zu drucken:

mehrere-beliebig-viele-pdf-dokumente-auf-einmal-drucken-bilder
Mehrere Bilddateien drucken mit „Windows Bilder drucken“

Fazit bleibt: Hier könnte Windows unbedingt nachbessern und einen umfangreicheren Druckservice anbieten, unabhängig von Anzahl, Typ und Ort der Datei sowie unabhängig von der Art der Ausgabe (Drucken, „To PDF“ usw.). Bis dahin sind Softwares wie Print Conductor schon die beste Möglichkeit für größere Druckvolumen.

windows-10-game-mode-teaserMit dem Windows 10 Creators Update veröffentlichte Microsoft den „Game Mode“. Es wird gemunkelt, dass der Modus Spiele generell schneller macht, ganz so einfach ist es natürlich nicht. Ich möchte kurz zusammenfassen, was der Modus bewirkt und was nicht.

Was macht der Game Mode?

Der Game Mode ist primär in der Lage, die zwei folgenden Punkte zu optimieren:

  • Die Verteilung/Priorität der CPU- und GPU-Ressourcen werden für das vordergründig laufende Spiel maximiert. Hintergrundanwendungen werden dadurch degradiert, aber bewusst nicht komplett geblockt.
  • CPU Kerne werden strikter aufgeteilt. Statt ein Spiel UND das System auf alle Kerne zu verteilen, bekommt das Spiel nicht alle aber dafür 100% dedizierte Kerne zugewiesen, das System bekommt die restlichen Kerne ebenfalls vollständig. Das Spiel sowie Prozesse des System sind somit separierter und unabhängiger.

via
Windows optimiert die Verarbeitung der Prozesse und Zuteilung von Ressourcen auf Softwareebene und priorisiert das Spiel. Die typischen Hintergrundprozesse (Antivirenscans, Sync-/Backup-/Datenprozesse, Video Encoding, Streaming usw.) werden mit weniger Ressourcen bedient und laufen damit langsamer.

Und das heißt jetzt?

Ein Szenario skizziert: Statt einem Spiel mit 4 weiteren Hintergrundprozessen jeweils 20% Ressourcen zuzuweisen, alles gleichmäßig auf 4 Prozessorkerne verteilt, bekommt das Spiel im Game Mode nun beispielsweise 80% und 3 volle Kerne, die 4 anderen Prozesse jeweils nur 5% auf dem vierten Kern. Heißt im Umkehrschluss, dass ein Spiel ohne Hintergrundprozesse auch bereits 100% Leistung bekommt und nicht von den Änderungen profitieren wird.
Somit ist der Game Mode vor allem dann geeignet, wenn viele oder größere Hintergrundprozesse das Spiel stören könnten und es unterschiedliche Lasten zu priorisieren gibt. Die positiven Auswirkungen zeigen sich dann durch wesentlich bessere minimale FPS, etwas bessere durchschnittliche oder maximale FPS und der Langzeitstabilität. Tests, die das gut zeigen, findet ihr beispielsweise auf hier auf pcworld.com (Ergebnisbilder folgend) oder rockpapershotgun.com. Folgend zwei Bilder von Ersterem Link, links ohne Hintergrundbelastung, rechts die Wirkung des Game Mode eines Systems mit Hintergrundlast:
windows-10-game-mode-pcworld.com-test-no-backgroundwindows-10-game-mode-pcworld.com-test-background-stuff

Heißt also einfach alle Programme offen lassen, Game Mode anschalten und alles schön? Ja und nein. Es stört vielleicht nicht weiter, wenn der wöchentliche Antivirenscan oder das wöchentliche Datenbackup auf die andere Festplatte doppelt so viel Zeit beanspruchen – die Tasks können nun beruhigt offen gelassen werden. Wichtige Programme könnten jedoch empfindlich gestört werden und ihre Arbeit nicht mehr wie benötigt verrichten, OBS Streaming als Beispiel genannt. Wählt eure laufenden Prozesse also weiterhin sorgfältig und testet auf Sideeffects bei kritischeren Programmen.
Leider gibt es noch keine Filterfunktionen, um einzelne Apps von der Optimierung auszuschließen, hier kann Microsoft sicher noch ausbessern.

Wie wird der Game Mode aktiviert?

Die meisten der Universal Windows Platform (UWP) und Win32 Spiele werden unterstützt, wobei es natürlicht immer Ausnahmen oder Probleme bei einzelnen Titeln geben kann. Bei unterstützten Titeln erscheint nach Drücken der Tastenkombination Win+G die Spieleleiste, in der ihr in den Einstellungen den Game Mode aktivieren könnt. Weitere Einstellungen bzw. die benötigte Tastenkombination (sollte Win+G nicht funktionieren) finden sich in den Windows Einstellungen -> Spiele.
windows-10-game-mode-bannerwindows-10-game-mode-options

Gruppenrichtlinien-Filterung

windows-ad-gpo-wmi-filter-intro-bannerDie Anweundung von Active Directory Gruppenrichtlinien lässt eine Filterung und Steuerung über verschiedene Techniken zu:

  • Verknüpfung mit OUs (die Voraussetzung ist gewissermaßen die erste Filterebene), Verknüpfungen aktivieren/deaktivieren
  • Sicherheitsfilterung mit Gruppen und Rechten
  • WMI-Filterung


Die ersten beiden sind gewissermaßen schon die Voraussetzung für das Erstellen und Anwenden einer Gruppenrichtlinie. Mit einer guten OU- und Gruppenstrukturen lassen sich bereits viele „Filter“ realisieren. Allerdings sind Rechte, Gruppen und OUs oftmals auch aufwändig in der Pflege.

Negativbeispiel: Mit einer „Windows10Clients“-Gruppe kann eine Filterung auf Sicherheitsebene vollzogen werden. Dazu muss die „Windows10Clients“-Gruppe jedoch händisch von den Admins gepflegt werden – neue Clients rein, alte Clients raus. Ebenso eine „SalesPCs“-Gruppe. In größeren Strukturen ist das nicht umsetzbar und geht auch einfacher.

Erweiterte Gruppenrichtlinienfilterung mit WMI

Hier kommen WMI-Filter ins Spiel. WMI, Windows Management Instrumentation, ist praktisch eine Schnittstelle zum Windows System, welches über Abfragen in einer Art SQL (WQL genannt) bedient wird und Informationen über das abgefragte System liefert. Solche Abfragen können ebenfalls für die Filterung von GPOs verwendet werden.

Beispiel: Wenn eine GPO nun also nur für Windows 10 Clients oder nur für Clients älter als Windows 10 übernommen werden soll, lassen sich die Clients super easy über WMI herausfiltern. Keine OU, keine Gruppen, nur 1 WMI-Objekt, im Endeffekt nur eine Zeile Code.

Mit Google oder Tools wie dem WMI Code Creator von Microsoft lassen sich somit schnell die benötigten Abfragen erstellen:
windows-ad-gpo-wmi-filter-code-creator-classes-processor-executewindows-ad-gpo-wmi-filter-code-creator-classes

Codebeispiele

Die Möglichkeiten sind vielseitig, hier ein paar Beispiele:

/* 32bit / 64bit */
SELECT * FROM Win32_OperatingSystem WHERE OSArchitecture = '32-Bit'
SELECT * FROM Win32_OperatingSystem WHERE OSArchitecture = '64-Bit'
/* Computername beginnt mit "vpc-" */
SELECT * FROM Win32_ComputerSystem WHERE Name LIKE 'vpc-%'
/* Sprache des Betriebssystems ist Deutsch */
SELECT * FROM Win32_OperatingSystem WHERE CountryCode = '49'
/* Internetexplorer ist in Version 8 installiert */
SELECT * FROM CIM_DataFile WHERE Filename = 'iexplore' AND version > '8.0' AND (path = '\\programme\\Internet Explorer\\' OR path = '\\program files\\Internet Explorer\\' )

via

Betriebssystemversion

Zum Erkennen des Betriebssystems eignen sich einige Variablen; von BuildNumber über Caption bis zu Version. Letztere ist einfach zu benutzen, da Microsoft für jede Betriebssystemversion plus dazu passende Servervariante die gleiche Version benutzt, weitere Infos dazu auf dieser Microsoft Seite.

/* Wählt alle Clients mit Windows Vista/7/8/8.1 (Nicht-Windows-10) */
SELECT * FROM Win32_OperatingSystem where Version like '6.%' and ProductType='1'
/* Windows 10 Clients only */
SELECT * FROM Win32_OperatingSystem where Version like '10.%' and ProductType='1'

Vorsicht: BuildNumber

Etwas nerviger ist die Abfrage der Windows Version anhand der BuildNumber, da diese nicht als Zahl sondern als String im System steht und somit einfache BuildNumber >= X Abfragen nicht funktionieren. Microsoft thematisiert das hier und wählt den Regex-ähnlichen Ansatz über die Anzahl der Ziffern in Kombination mit der BuildNumber. Auch Marc von gruppenrichtlinien.de verwendet WHERE BuildNumber > '5000' – das alles lief bei mir nicht zuverlässig. BuildNumber scheint mir ein schlechtes Werkzeug zu sein und ich gehe daher über die Betriebssystem Caption, die sehr standardisiert ist:

/* Windows 10 Clients */
SELECT * FROM Win32_OperatingSystem WHERE Caption LIKE '%10%' AND BuildNumber LIKE '[123456789][0123456789][0123456789][0123456789][0123456789]'
/* Alle Clients vor Windows 10 */
SELECT * FROM Win32_OperatingSystem WHERE NOT Caption LIKE '%10%' AND BuildNumber LIKE '[123456789][0123456789][0123456789][0123456789]'

Das hat bei Win7 und Win10 funktioniert wie erwünscht.
windows-ad-gpo-wmi-filter-in-use-os-version-buildnumber