michi.wtr
Goto Top

Drucker Remote Installation PowerShell

Hey zusammen,

vor kurzem habe ich ein kleines Skript geschrieben, welches Drucker auf einem Client lokal hinzufügen kann.
Das ganze läuft über eine Auswahl von

$printerlist = Import-Csv \\Pfad\zur\PrinterListe.csv -Delimiter ';' -Encoding UTF7 | Out-Gridview -Passthrough  

In der CSV stehen Name + Standord des Druckers und Informationen wie DruckerIP, DruckerIP und Treiberpfad.
Somit ist $printerlist ein Object[ ] mit

printerlist

Mit folgendem Code füge ich den Drucker ohne Probleme hinzu, wenn ich das Skript (zusammen mit dem Code oben) lokal auf dem Computer ausführe. Ich werde aufgefordert für die Installation (printui.exe) ggf. die Credentials eines Adminkontos anzugeben.

foreach ($printer in $printerlist) {
    $newPort = ([wmiclass]"Win32_TcpIpPrinterPort").CreateInstance()  
    $newPort.HostAddress = $printer.PrinterIP
    $newPort.Name = "IP_$($printer.PrinterIP)"  
    $newPort.PortNumber = "9100"  
    $newPort.Protocol = 1
    $newPort.Put()

    if (-not $?) {$fail += $printer}

    printui /if /b "$($printer.PrinterID)" /f "$($printer.DriverINFPath)" /u /r "$($newPort.Name)" /m "$($printer.PrinterModel)"  
}

Führe ich denselben Code aber als ScriptBlock aus:

$sbstring = "`$printerlist = @();`r`n"  

$printerlist |% {
$sbstring += "`$printerlist += [pscustomobject]@{Werk='$($_.Werk)';  
                                                 PrinterID='$($_.PrinterID)';  
                                                 PrinterModel='$($_.PrinterModel)';  
                                                 PrinterIP='$($_.PrinterIP)';  
                                                 DriverINFPath='$($_.DriverINFPath)'}`r`n"  
}

$sbstring += "foreach (`$printer in `$printerlist){  
`$newPort = ([wmiclass]`"Win32_TcpIpPrinterPort`").CreateInstance();  
`$newPort.HostAddress = `$printer.PrinterIP;
`$newPort.Name = `"IP_`$(`$printer.PrinterIP)`";  
`$newPort.PortNumber = '9100';  
`$newPort.Protocol = 1;
`$newPort.Put();
}"  

$scriptBlock = [System.Management.Automation.ScriptBlock]::Create($sbstring)

& $scriptBlock

So bekomme ich zwar den gleichen Output, der eigentlich auf ein erfolgreiches Vorgehen hindeutet:

output

jedoch ist der Drucker nicht hinzugefügt... Auch nach Neustart oder ab- und anmelden leider immer noch nicht hinzugefügt. Lasse ich mir den ScriptBlock aber anzeigen, so steht 1:1 der gleiche Code in der Konsole. Auch das Object printerlist habe ich überprüft, und wenn ich die Parameter im ScriptBlock ausgebe, so erscheinen diese wie gewollt auch auf der Konsole.....

Wenn ich nicht auch die Rückmeldung über das erfolgreiche hinzufügen bekommen würde, wäre ich auch nicht so verwundert. Die Idee war einfach, dass ich den ScriptBlock dann mit

Invoke-Command -Computername (Read-Host "Computername") -Credential (Get-Credential -Message "Administrator User for Remote Client") -ScriptBlock $scriptBlock  

auf dem Zielcomputer ausführe und durch die Credentials des Adminusers automatisch der ScriptBlock auch mit Adminrechten ausgeführt wird.

Ich habe auch gelesen, dass man statt dem ScriptBlock auch einen FilePath für ein ganzes Script übergeben kann, jedoch kann ich auch da mein ursprüngliches Skript nicht nehmen wegen der Out-Gridview Abfrage. Sollte ich einfach eine Gridview Abfrage an Invoke-Command -FilePath (2. Teil vom Skript) pipen mit ($printerlist | ConvertTo-Csv -Delimiter ';') als Argument?

Vielen lieben Dank schonmal im Voraus und sorry für den Roman,
Micha face-smile

Content-Key: 6076121225

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

Printed on: April 27, 2024 at 17:04 o'clock

Mitglied: 6017814589
Solution 6017814589 Feb 22, 2023 updated at 06:43:31 (UTC)
Goto Top
jedoch ist der Drucker nicht hinzugefügt.
Du fügst im Scriptblock ja auch nur den Port hinzu aber nicht das Druckerobjekt selbst, das hast du vergessen 😉
p.s das intensive Escaping ist überflussig einen Skriptblock kannst du ganz einfach per {} erstellen ohne das ganze Escaping ganz normal reinschreiben. Und auf Variablen außerhalb des Remote Skriptblocks kannst du im Remote-Skriptblock mittels $using:printerlist zugreifen, oder du nutzt den Parameter "-ArgumentList" und übergibst die Variable an den Skriptblock und nutzt darin dann param($variable) im Header ...

Variante "Using"
$printerlist = Import-Csv \\Pfad\zur\PrinterListe.csv -Delimiter ';' -Encoding UTF7 | Out-Gridview -Passthrough  
Invoke-Command -Computername (Read-Host "Computername") -Credential (Get-Credential -Message "Administrator User for Remote Client") -ScriptBlock {  
  foreach ($printer in $using:printerlist) {
    $newPort = ([wmiclass]"Win32_TcpIpPrinterPort").CreateInstance()  
    $newPort.HostAddress = $printer.PrinterIP
    $newPort.Name = "IP_$($printer.PrinterIP)"  
    $newPort.PortNumber = "9100"  
    $newPort.Protocol = 1
    $newPort.Put()

    if (-not $?) {$fail += $printer}

    printui /if /b "$($printer.PrinterID)" /f "$($printer.DriverINFPath)" /u /r "$($newPort.Name)" /m "$($printer.PrinterModel)"  
  }
}

Variante "Argumentlist"

$printerlist = Import-Csv \\Pfad\zur\PrinterListe.csv -Delimiter ';' -Encoding UTF7 | Out-Gridview -Passthrough  
Invoke-Command -Computername (Read-Host "Computername") -Credential (Get-Credential -Message "Administrator User for Remote Client") -Argumentlist @($printerlist) -ScriptBlock {  
  param($printers)
  foreach ($printer in $printers) {
    $newPort = ([wmiclass]"Win32_TcpIpPrinterPort").CreateInstance()  
    $newPort.HostAddress = $printer.PrinterIP
    $newPort.Name = "IP_$($printer.PrinterIP)"  
    $newPort.PortNumber = "9100"  
    $newPort.Protocol = 1
    $newPort.Put()

    if (-not $?) {$fail += $printer}

    printui /if /b "$($printer.PrinterID)" /f "$($printer.DriverINFPath)" /u /r "$($newPort.Name)" /m "$($printer.PrinterModel)"  
  }
}

p.s2 Es gibt auch Add-Printerport und Add-Printer und Add-Printerdriver
https://learn.microsoft.com/en-us/powershell/module/printmanagement/?vie ...
Member: michi.wtr
michi.wtr Feb 22, 2023 at 08:24:41 (UTC)
Goto Top
Quote from @6017814589:

Du fügst im Scriptblock ja auch nur den Port hinzu aber nicht das Druckerobjekt selbst, das hast du vergessen 😉

Danke xD. Ja jetzt funktioniert das auch, dachte diese Meldung kommt durch printui, nicht durch den $newPort.Put( ). Das mit dem $using: kannte ich noch gar nicht, bzw. das mit der Argumentlist :D aber das funktioniert jetzt prima und ist auch viel angenehmer den ScriptBlock zu erstellen ohne diese String Escapes.

Add-Printer, Add-Printerport und Add-Printerdriver hatte ich auch schon gesehen, hatte das mit help Add-Printer etc. aber nicht ganz verstanden.

Vielen lieben Dank o/