Power Shell Skript - Drucker Liste + Löschfunktion
Guten Mittag,
nach langem herumprobieren habe ich mich entschlossen doch einmal Nachzufragen. Was Power Shell angeht bin Ich leider ein ziemlicher Neuling.
Nun zu meinem Vorhaben:
Es soll eine Liste der Lokal installierten Drucker ausgegeben werden, hierführ habe ich auch schon eine Möglichkeit gefunden (Get-Printer). Es soll auch möglich sein einige Druckernamen azugeben die später durch eine If abfrage mit den ausgelesen verglichen werden soll. Dann sollen alle Drucker gelöscht werden die nicht der festgelegten Namensliste entsprechen.
-Bitte nicht einfach eine Lösung posten, ich benötige den Lerneffekt!
Ich freue mich auf eure Hinweise wie ich mein Vorhaben umgesetzt bekomme.
Mit freundlichen Grüßen
mertaufmberg
nach langem herumprobieren habe ich mich entschlossen doch einmal Nachzufragen. Was Power Shell angeht bin Ich leider ein ziemlicher Neuling.
Nun zu meinem Vorhaben:
Es soll eine Liste der Lokal installierten Drucker ausgegeben werden, hierführ habe ich auch schon eine Möglichkeit gefunden (Get-Printer). Es soll auch möglich sein einige Druckernamen azugeben die später durch eine If abfrage mit den ausgelesen verglichen werden soll. Dann sollen alle Drucker gelöscht werden die nicht der festgelegten Namensliste entsprechen.
-Bitte nicht einfach eine Lösung posten, ich benötige den Lerneffekt!
Ich freue mich auf eure Hinweise wie ich mein Vorhaben umgesetzt bekomme.
Mit freundlichen Grüßen
mertaufmberg
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 466584
Url: https://administrator.de/contentid/466584
Ausgedruckt am: 24.11.2024 um 04:11 Uhr
7 Kommentare
Neuester Kommentar
Moin,
Das ist doch mal eine Ansage. Vorbemerkung: Die Powershell ist eine streng objektorientierte Sprache. Alles ist ein Objekt. Objekte haben Eigenschaften und man kann Methoden auf sie anwenden. Will man eine Eigenschaft eines Objekts ansprechen, dann hängt man die Eigenschaft einfach mit Punkt getrennt an den Namen des Objektes an.
Den Befehl get-printer hast Du ja schon gefunden. Dieser Befehl gibt Dir alle Druckerobjekte des Rechners zurück. Wenn Du mal wissen willst, was da alles zurückgegeben wird, dann gib
ein. Hmmm, was ist dieser |? Das ist die Pipe. Mit der Pipe kannst Du die Ausgabe eines Befehls an einen anderen Befehl übergeben. Sehr praktisch. Um jetzt Dein Anliegen erledigen zu können, müssen wir das Ergebnis des Befehls erst einmal in eine Variable schreiben.
Die Variable $printers enthält nun ein Array der Druckerobjekte. Jetzt fehlt noch die Liste. Die steht wahrscheinlich in einer Textdatei. Also lesen wir die Textdatei auch in eine Variable ein:
Jetzt haben wir ein weiteres Array, in dem die einzelnen Zeilen der Liste stehen. Wir können also nachschauen, ob der Name des Druckers in der Liste steht. Das machen wir am Besten mit einer foreach-Schleife.
Innerhalb der Schleife steht in der Variablen $printer bei jedem Durchlauf das aktuelle Druckerobjekt. Das fragen wir nach seinem Namen und vergleichen den Namen mit der Liste. Das geht mit einem if-Statement.
So sieht das mal im Groben aus. Du wolltest ja lernen. Das funktioniert nur dann, wenn die legalen Drucker wirklich den Namen haben, der in der Liste steht. Falls nicht, fliegen die auch raus. Eventuell brauchst Du hier einen Vergleich mit regulären Ausdrücken. Aber versuche es erstmal so.
Nochmal komplett und ungetestet:
hth
Erik
Zitat von @mertaufmberg:
Guten Mittag,
nach langem herumprobieren habe ich mich entschlossen doch einmal Nachzufragen. Was Power Shell angeht bin Ich leider ein ziemlicher Neuling.
Nun zu meinem Vorhaben:
Es soll eine Liste der Lokal installierten Drucker ausgegeben werden, hierführ habe ich auch schon eine Möglichkeit gefunden (Get-Printer). Es soll auch möglich sein einige Druckernamen azugeben die später durch eine If abfrage mit den ausgelesen verglichen werden soll. Dann sollen alle Drucker gelöscht werden die nicht der festgelegten Namensliste entsprechen.
-Bitte nicht einfach eine Lösung posten, ich benötige den Lerneffekt!
Guten Mittag,
nach langem herumprobieren habe ich mich entschlossen doch einmal Nachzufragen. Was Power Shell angeht bin Ich leider ein ziemlicher Neuling.
Nun zu meinem Vorhaben:
Es soll eine Liste der Lokal installierten Drucker ausgegeben werden, hierführ habe ich auch schon eine Möglichkeit gefunden (Get-Printer). Es soll auch möglich sein einige Druckernamen azugeben die später durch eine If abfrage mit den ausgelesen verglichen werden soll. Dann sollen alle Drucker gelöscht werden die nicht der festgelegten Namensliste entsprechen.
-Bitte nicht einfach eine Lösung posten, ich benötige den Lerneffekt!
Das ist doch mal eine Ansage. Vorbemerkung: Die Powershell ist eine streng objektorientierte Sprache. Alles ist ein Objekt. Objekte haben Eigenschaften und man kann Methoden auf sie anwenden. Will man eine Eigenschaft eines Objekts ansprechen, dann hängt man die Eigenschaft einfach mit Punkt getrennt an den Namen des Objektes an.
Den Befehl get-printer hast Du ja schon gefunden. Dieser Befehl gibt Dir alle Druckerobjekte des Rechners zurück. Wenn Du mal wissen willst, was da alles zurückgegeben wird, dann gib
get-printer | select *
ein. Hmmm, was ist dieser |? Das ist die Pipe. Mit der Pipe kannst Du die Ausgabe eines Befehls an einen anderen Befehl übergeben. Sehr praktisch. Um jetzt Dein Anliegen erledigen zu können, müssen wir das Ergebnis des Befehls erst einmal in eine Variable schreiben.
$printers = get-printer
Die Variable $printers enthält nun ein Array der Druckerobjekte. Jetzt fehlt noch die Liste. Die steht wahrscheinlich in einer Textdatei. Also lesen wir die Textdatei auch in eine Variable ein:
$liste = get-content liste.txt -encoding utf8 # Oder ein anderes encoding. Je nach dem, was das ist.
Jetzt haben wir ein weiteres Array, in dem die einzelnen Zeilen der Liste stehen. Wir können also nachschauen, ob der Name des Druckers in der Liste steht. Das machen wir am Besten mit einer foreach-Schleife.
foreach($printer in $printers) {
#mach was mit jedem Druckerobjekt
}
Innerhalb der Schleife steht in der Variablen $printer bei jedem Durchlauf das aktuelle Druckerobjekt. Das fragen wir nach seinem Namen und vergleichen den Namen mit der Liste. Das geht mit einem if-Statement.
if(-not ($liste -contains $printer.name) { # -contains prüft, ob ein Array einen Wert enthält und -not negiert den Vergleich
remove-printer $printer
}
So sieht das mal im Groben aus. Du wolltest ja lernen. Das funktioniert nur dann, wenn die legalen Drucker wirklich den Namen haben, der in der Liste steht. Falls nicht, fliegen die auch raus. Eventuell brauchst Du hier einen Vergleich mit regulären Ausdrücken. Aber versuche es erstmal so.
Nochmal komplett und ungetestet:
$printers = get-printer
$liste = get-content liste.txt -encoding utf8 # Oder ein anderes encoding. Je nach dem, was das ist.
foreach($printer in $printers) {
if(-not ($liste -contains $printer.name) {
remove-printer $printer
}
}
hth
Erik
Servus mertaufmberg.
Ich beschreibe dir mal einen davon mit ausführlicher Beschreibung, du darfs dann mal eine andere Variante davon selbst erzeugen:
Du holst dir die Drucker mit deinem schon genannten CMDLet (wäre auch ohne dieses über WMI möglich (gcim WIN32_Printer), aber das nur am Rande)
Das Ergebnis der Ausgabe sind die Drucker als Objekte welche unter anderen eine Eigenschaft mit dem Namen Name hat. Das behalten wir im Hinterkopf.
Nun brauchen wir eine Speichermöglichkeit für mehrere Namen. Dafür bietet sich ein einfaches String-Array an
Jetzt brauchen wir noch einen Befehl zum Löschen eines Druckers. Da bietet sich, wär hätte es gedacht, Remove-Printer an.
So damit haben wir schon fast alles was wir brauchen. Wir müssen es nur noch miteinander verknüpfen.
Da man in Powershell ziemlich viel über die Pipeline machen kann (d.h. Befehle und deren Ergebnisse an folgende Befehle mit dem (|) Pipe-Symbol verknüpfen machen wird das hier exemplarisch, denn es bietet sich gerade zu an:
Dazu Senden wir die Ausgabe des CMDLets Get-Printer an das CMDLet where-object welches dafür da ist aus einem Array bestimmte Objekte auszufiltern.
in den {} des Where-Objects definieren wir die Boolsche Bedingung die True oder False ergeben sollte. In der Bedingung ist das $_ das aktuelle Objekt in der Pipeline von Get-Printer. Da das ja ein Objekt ist und wir die Name Eigenschaft davon für einen Vergleich heranziehen möchten rufen wird diese Eigenschaft vom Objekt ab und erhalten dieses Konstrukt $_.Name was inhaltlich den Namen des Druckers enthält. Nun müssen wir ja prüfen ob der Druckername im Array oder nicht enthalten ist. Dafür gibt es zwei Vergleiochoperatoren -in welcher prüft ob ein Element in einem Array enthalten ist, oder -notin welcher prüft ob ein Element nicht in einem Array vorkommt (Alternativ gibt es auch -contains -und -notcontains wenn man als erstes Argument das Array statt de, Element angibt). Da wir die Drucker welche nicht im Array vorkommen löschen möchten, wählen wir hier -notin als Operator. Nun gibt man als nächstes das Vergleichselement an mit dem wir den Namen vergleichen möchten, in diesem Fall unser Array mit den vordefinierten Druckernamen liegen.
Das Where Object (Abkürzung bzw. Alias übrigens ?{}) übergibt nur die Objekte weiter welche mit der Bedingung übereinstimmen, da wir diese nun nur noch löschen möchten hängen wir das Remove-Printer einfach in die Pipeline (denn wir haben ja gelernt, die Powershell mag die Pipeline besonders .
In Code sieht das dann rudimentär so aus.
Das ganze kannstdu auch auf herkömmliche Art und Weise mit einer Foreach-Schleife und darin einem IF-Konstrukt machen, das lass ich dir jetzt mal als Hausaufgabe (-edit- erik hat's dir scchon abgenommen .)
Grüße Uwe
Bitte nicht einfach eine Lösung posten, ich benötige den Lerneffekt!
Da gibt es wie immer 100 Wege nach Rom.Ich beschreibe dir mal einen davon mit ausführlicher Beschreibung, du darfs dann mal eine andere Variante davon selbst erzeugen:
Du holst dir die Drucker mit deinem schon genannten CMDLet (wäre auch ohne dieses über WMI möglich (gcim WIN32_Printer), aber das nur am Rande)
Get-Printer
Nun brauchen wir eine Speichermöglichkeit für mehrere Namen. Dafür bietet sich ein einfaches String-Array an
$druckernamen = "Drucker1",Drucker2","Drucker3"
So damit haben wir schon fast alles was wir brauchen. Wir müssen es nur noch miteinander verknüpfen.
Da man in Powershell ziemlich viel über die Pipeline machen kann (d.h. Befehle und deren Ergebnisse an folgende Befehle mit dem (|) Pipe-Symbol verknüpfen machen wird das hier exemplarisch, denn es bietet sich gerade zu an:
Dazu Senden wir die Ausgabe des CMDLets Get-Printer an das CMDLet where-object welches dafür da ist aus einem Array bestimmte Objekte auszufiltern.
in den {} des Where-Objects definieren wir die Boolsche Bedingung die True oder False ergeben sollte. In der Bedingung ist das $_ das aktuelle Objekt in der Pipeline von Get-Printer. Da das ja ein Objekt ist und wir die Name Eigenschaft davon für einen Vergleich heranziehen möchten rufen wird diese Eigenschaft vom Objekt ab und erhalten dieses Konstrukt $_.Name was inhaltlich den Namen des Druckers enthält. Nun müssen wir ja prüfen ob der Druckername im Array oder nicht enthalten ist. Dafür gibt es zwei Vergleiochoperatoren -in welcher prüft ob ein Element in einem Array enthalten ist, oder -notin welcher prüft ob ein Element nicht in einem Array vorkommt (Alternativ gibt es auch -contains -und -notcontains wenn man als erstes Argument das Array statt de, Element angibt). Da wir die Drucker welche nicht im Array vorkommen löschen möchten, wählen wir hier -notin als Operator. Nun gibt man als nächstes das Vergleichselement an mit dem wir den Namen vergleichen möchten, in diesem Fall unser Array mit den vordefinierten Druckernamen liegen.
Das Where Object (Abkürzung bzw. Alias übrigens ?{}) übergibt nur die Objekte weiter welche mit der Bedingung übereinstimmen, da wir diese nun nur noch löschen möchten hängen wir das Remove-Printer einfach in die Pipeline (denn wir haben ja gelernt, die Powershell mag die Pipeline besonders .
In Code sieht das dann rudimentär so aus.
$druckernamen = "Drucker1",Drucker2","Drucker3"
Get-Printer | Where {$_.Name -notin $druckernamen} | Remove-Printer -Confirm:$false
Grüße Uwe
jetzt mal als Hausaufgabe (-edit- erik hat's dir scchon abgenommen .)
Ich war so frei. Ich finde das für Anfänger auch besser, da die Lernkurve der Pipe vor allem für Windows-User doch recht steil ist. Pipes werden relativ schnell kryptisch.
Ich war so frei. Ich finde das für Anfänger auch besser, da die Lernkurve der Pipe vor allem für Windows-User doch recht steil ist. Pipes werden relativ schnell kryptisch.
Noch ein wenig Literatur zum Einstieg:
https://docs.microsoft.com/de-de/powershell/
https://www.martinlehmann.de/wp/download/powershell-openbook/
https://docs.microsoft.com/de-de/powershell/
https://www.martinlehmann.de/wp/download/powershell-openbook/
Wenn nur alle so lernwillig wären ...