mertaufmberg
Goto Top

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

Content-ID: 466584

Url: https://administrator.de/contentid/466584

Ausgedruckt am: 24.11.2024 um 04:11 Uhr

erikro
Lösung erikro 27.06.2019 aktualisiert um 15:09:50 Uhr
Goto Top
Moin,
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!

Das ist doch mal eine Ansage. face-wink 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. face-wink 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
colinardo
Lösung colinardo 27.06.2019 aktualisiert um 15:09:37 Uhr
Goto Top
Servus mertaufmberg.
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
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
$druckernamen = "Drucker1",Drucker2","Drucker3"  
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 face-wink.
In Code sieht das dann rudimentär so aus.
$druckernamen = "Drucker1",Drucker2","Drucker3"  
Get-Printer | Where {$_.Name -notin $druckernamen} | Remove-Printer -Confirm:$false
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 face-wink.)

Grüße Uwe
erikro
Lösung erikro 27.06.2019 um 15:13:34 Uhr
Goto Top
Zitat von @colinardo:
jetzt mal als Hausaufgabe (-edit- erik hat's dir scchon abgenommen face-wink.)

Ich war so frei. face-wink 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. face-wink
colinardo
Lösung colinardo 27.06.2019 aktualisiert um 15:16:53 Uhr
Goto Top
Jetzt hat und kann er beides lernen und für sich wählen face-smile.
mertaufmberg
mertaufmberg 27.06.2019 um 15:42:50 Uhr
Goto Top
Vielen Lieben Dank an euch!!! Werde mich gleich dran versuchen face-smile

Ich wünsche noch einen schönen Tag

-mertaufmberg
erikro
erikro 27.06.2019 um 15:52:46 Uhr
Goto Top
erikro
erikro 27.06.2019 um 15:53:31 Uhr
Goto Top
Zitat von @colinardo:

Jetzt hat und kann er beides lernen und für sich wählen face-smile.

Wenn nur alle so lernwillig wären ...