none
Funktion auf Remote Server ausführen RRS feed

  • Frage

  • Hallo,

    folgendes möchte ich mit meinem Skript erreichen:

    Das Skript soll auf einem Terminalserver ausgeführt werden. Dabei soll es verschiedene commands aus der Funktion remote auf 20+ anderen Servern ausführen und den Output dann in eine file schreiben, sodass ich am Ende eine Datei habe mit dem Output von allen Servern.

    Ich habe das hier mal wie folgt probiert, jedoch wird mir hier eine Fehlermeldung geworfen, da es anscheinend ein Problem mit meinem Invoke-command gibt. Nach Recherche kann ich meinen Fehler allerdings nicht erkennen.

    Ich hatte auch bereits einen anderen Ansatz, bei dem ich das was in der Funktion steht in ein anderes Skript auslagere und dieses über den Invoke Command ausführen. Das hatte eigentlich besser funktioniert aber es gab Probleme den Output in eine Datei zu schreiben, da das Skript nicht als Administrator ausgeführt wurde. Dann bekam ich einen Fehler da ich nicht auf den file share zugreifen durfte wo der Output hingeschrieben werden sollte (das ging bei manchen servern aber nicht bei allen). Gibt es hier eine Möglichkeit den INvoke-command als Admin auf dem Server laufen zu lassen?

    Oder was ist mein Fehler in dem folgenden Skript?

    function get-infofromremoteserver
    {
    
    $systeminfo = Get-CimInstance -ClassName win32_operatingsystem | select csname, lastbootuptime
    $gpresult = gpresult /scope computer /r | findstr "SG_Test"
    #$systeminfo, $gpresult | out-file -filepath Y:\TKAADMIN\Tetes\dump.txt -append -width 200
    Write-Output "GGGGG"
    return $systeminfo, $gpresult
     
    }
    
    
    $c = Get-Credential -Message "Please enter your username and password to access the server" 
    $User = "Admin"
    #$PWord = ConvertTo-SecureString -String  -AsPlainText -Force
    #$Credential = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $User, $PWord
    
    $resultsFolderPath = "Y:\TKAADMIN\Tetes\dump.txt"
    $Path = "Y:\TKAADMIN\Tetes\serverlist.csv"
    $servers = Import-Csv -Path  Y:\TKAADMIN\Tetes\serverlist.csv -Delimiter ";" -Encoding UTF8
    Write-Output $servers.server
    
    
    
    foreach ($server in $servers)
    {
        
        Write-Output "Hafff"
        $session = New-PSSession -ComputerName $server.server -Credential $c
        Invoke-Command -Computername $server -ScriptBlock ${function:get-infofromremoteserver} -Session $session | Select-Object systeminfo, gpresult
        #Invoke-Command -FilePath Y:\TKAADMIN\Justatest.ps1 -Session $session
    
       #Write-Output $systeminfo, $gpresult
    
        "################   " + $systeminfo.csname +  "   ################" | Out-file -FilePath $resultsFolderPath -append
    $systeminfo | Out-file -FilePath $resultsFolderPath -append
    "GPRESULT: " | Out-file -FilePath $resultsFolderPath -append
    $gpresult | Out-file -FilePath $resultsFolderPath -append
    " " | Out-file -FilePath $resultsFolderPath -append
    "###########################################################" | Out-file -FilePath $resultsFolderPath -append
    " " | Out-file -FilePath $resultsFolderPath -append
        
        
       
    }
    
    
    

    Fehlermeldung

    Invoke-Command : One or more computer names are not valid. If you are trying to pass a URI, use the -ConnectionUri parameter, or pass URI objects instead of strings.
    At Y:\TKAADMIN\ReadOutLastRebootandGPOs.ps1:33 char:5
    +     Invoke-Command -Credential $c -Computername $server -scriptblock  ...
    +     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidArgument: (System.String[]:String[]) [Invoke-Command], ArgumentException
        + FullyQualifiedErrorId : PSSessionInvalidComputerName,Microsoft.PowerShell.Commands.InvokeCommandCommand

    Freitag, 21. August 2020 07:19

Antworten

  • Das scheint er auch auszuführen aber ich bekomme danach keine Werte zurück in $systeminfo und $gpresult

    Wie auch? Du füllst die Variablen im Inneren des Script-Blocks. Und nur da existieren sie. ;-)

    Probier mal das hier:

    $session = 
        New-PSSession -ComputerName $server.server -Credential $c
    
    $systeminfo = 
        Invoke-Command -Session $session -ScriptBlock { 
            Get-CimInstance -ClassName win32_operatingsystem | 
                Select-Object csname, lastbootuptime
        }
    $systeminfo
    Für die zweite Abfrage mit gpresult kannst Du einen zweiten Scriptblock machen.

    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    • Bearbeitet BOfH-666 Freitag, 21. August 2020 13:59
    • Als Antwort markiert tim--97 Montag, 24. August 2020 08:31
    Freitag, 21. August 2020 13:54
  • Ok, ich habe nun auch noch den den Remove-PSSession command eingebunden, danke für den Hinweis.

    Hier nun der funktionierende foreach Teil:

    foreach ($server in $servers)
    {
        Write-Output "Server: " $server.server
      
        $session = New-PSSession -ComputerName $server.server -Credential $c
    
        $systeminfo = 
        Invoke-Command -Session $session -ScriptBlock { 
            Get-CimInstance -ClassName win32_operatingsystem | 
                Select-Object csname, lastbootuptime
        }
    $systeminfo
    
        $gpresult = 
        Invoke-Command -Session $session -ScriptBlock { 
            gpresult /scope computer /r | findstr "SG_"
        }
    $gpresult
    
    Remove-PSSession -ComputerName $server.server
    
        "################   " + $systeminfo.csname +  "   ################" | Out-file -FilePath $resultsFolderPath -append
    $systeminfo | Out-file -FilePath $resultsFolderPath -append
    "GPRESULT: " | Out-file -FilePath $resultsFolderPath -append
    $gpresult | Out-file -FilePath $resultsFolderPath -append
    " " | Out-file -FilePath $resultsFolderPath -append
    "###########################################################" | Out-file -FilePath $resultsFolderPath -append
    " " | Out-file -FilePath $resultsFolderPath -append
    #Clear-Variable systeminfo, gpresult
    
       
    }


    • Als Antwort markiert tim--97 Montag, 24. August 2020 08:31
    Montag, 24. August 2020 08:31

Alle Antworten

  • Moin,

    ich hatte Dir schon geantwortet, aber Du musstest ja den ganzen Thread löschen. Noch einmal:

    1. Invoke-Command erwartet *entweder* eine aufgebaute und authentifizierte PSSession, *oder* ComputerName, ConfigurationName usw.
    2. Der ScriptBlock wird verbatim auf dem Remote-Computer ausgeführt. Da dort Deine Funktion nicht definiert ist, wird es ins Leere laufen. Du musst nicht den Namen, sondern den Text der Funktion als ScriptBlock mitgeben.
    3. Kosmetik/Optimierung: Wenn ein Satz von Credentials für alle oder viele Server gilt, übergib deren Namen als Array an Invoke-Command, dann wird das parallel ausgeführt.

    Evgenij Smirnov

    http://evgenij.smirnov.de

    Freitag, 21. August 2020 07:28
  • Ja ich hatte da irgendwie Mist gebaut.

    Danke für deine Antwort...

    zu 1. die PSSession habe ich ja vorher bereits aufgebaut und authentifiziert oder was meinst du?

    zu 2. Wie kann ich denn die einzelnen Commands im Scriptblock voneinander separieren oder 1:1 aus der Funktion in den SB kopieren?

    zu 3. Du meinst ich soll die Computernamen in ein array speichern und das dann an Invoke Command übergeben? dachte $c ist automatisch ein array da dort ja mehrere values übergeben werden aus der CSV


    Freitag, 21. August 2020 10:12
  • Moin,

    ad 1. Wenn Du die PSSession bereits aufgebaut hast, dann übergib auch nur die. -Computername ist dann überflüssig, da die Session ja bereits zu einem bestimmten Computer aufgebaut ist.

    ad 2. Entweder Semikolon nach jedem Befehl und hintereinander schreiben, oder Text in Here-String und dann nach [scriptblock] casten

    ad 3. Ich meine sowas:

    $computers = @('SRV01','SRV02','SRV0815','SRV4711')
    $creds = Get-Credential
    Invoke-Command -ComputerName $computers -Credential $creds -ScriptBlock {foreach ($x in (Get-Blah)){ Remove-Suelz -Identity $x.Id; Write-Output "Suelz $($x.Name) removed"}}


    Evgenij Smirnov

    http://evgenij.smirnov.de

    Freitag, 21. August 2020 10:19
  • zu 2. Wie kann ich denn die einzelnen Commands im Scriptblock voneinander separieren

    Was spricht denn gegen den klassischen Zeilenumbruch?  ... oder hab ich was falsch verstanden?

    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Freitag, 21. August 2020 13:02
  •     Invoke-Command -Computername $server -ScriptBlock {$systeminfo = Get-CimInstance -ClassName win32_operatingsystem | select csname, lastbootuptime;
    $gpresult = gpresult /scope computer /r | findstr "SG_CGM.WSUS";
    Write-Output "GGGGG"} -Session $session | Select-Object systeminfo, gpresult

    Wirft folgenden Fehler:

    Invoke-Command : Parameter set cannot be resolved using the specified named parameters.
    At Y:\TKAADMIN\ReadOutLastRebootandGPOs.ps1:19 char:5
    +     Invoke-Command -Computername $server -ScriptBlock {$systeminfo =  ...
    +     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidArgument: (:) [Invoke-Command], ParameterBindingException
        + FullyQualifiedErrorId : AmbiguousParameterSet,Microsoft.PowerShell.Commands.InvokeCommandCommand

    zu 3. Ich glaube ich muss die Commands nacheinander auf den Server ausführen, da ich den Output also $gpresult und $systeminfo ja wegschreiben will. Wenn ich die commands zur gleichen Zeit ausführe dann funktioniert dies doch nicht oder?

    Freitag, 21. August 2020 13:03
  • Was ist denn der unterschied zwischen folgendem:

    $session = New-PSSession -ComputerName $server -Credential $c
    
    Invoke-Command -ScriptBlock {Get-Help} -Session $session
    
    
    ODER
    
    Invoke-Command -Computername $server -Credentials $c -ScriptBlock {Get-Help}
    
    
    
    
    
    
    

    Soll im Endeffekt doch das gleiche machen nur das WIE ist anders oder?

    Freitag, 21. August 2020 13:09
  •     Invoke-Command -Computername $server -ScriptBlock {$systeminfo = Get-CimInstance -ClassName win32_operatingsystem | select csname, lastbootuptime;
    $gpresult = gpresult /scope computer /r | findstr "SG_CGM.WSUS";
    Write-Output "GGGGG"} -Session $session | Select-Object systeminfo, gpresult

    Wirft folgenden Fehler:

    Invoke-Command : Parameter set cannot be resolved using the specified named parameters.
    At Y:\TKAADMIN\ReadOutLastRebootandGPOs.ps1:19 char:5
    +     Invoke-Command -Computername $server -ScriptBlock {$systeminfo =  ...
    +     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidArgument: (:) [Invoke-Command], ParameterBindingException
        + FullyQualifiedErrorId : AmbiguousParameterSet,Microsoft.PowerShell.Commands.InvokeCommandCommand

    Habs jetzt doch mit PSSession gemacht.

        $session = New-PSSession -ComputerName $server.server -Credential $c
    
        Invoke-Command -ScriptBlock {$systeminfo = Get-CimInstance -ClassName win32_operatingsystem | select csname, lastbootuptime
    $gpresult = gpresult /scope computer /r | findstr "SG_CGM.WSUS"
    Write-Output "GGGGG"} -Session $session
    Das scheint er auch auszuführen aber ich bekomme danach keine Werte zurück in $systeminfo und $gpresult

    Freitag, 21. August 2020 13:23
  • Das scheint er auch auszuführen aber ich bekomme danach keine Werte zurück in $systeminfo und $gpresult

    Wie auch? Du füllst die Variablen im Inneren des Script-Blocks. Und nur da existieren sie. ;-)

    Probier mal das hier:

    $session = 
        New-PSSession -ComputerName $server.server -Credential $c
    
    $systeminfo = 
        Invoke-Command -Session $session -ScriptBlock { 
            Get-CimInstance -ClassName win32_operatingsystem | 
                Select-Object csname, lastbootuptime
        }
    $systeminfo
    Für die zweite Abfrage mit gpresult kannst Du einen zweiten Scriptblock machen.

    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    • Bearbeitet BOfH-666 Freitag, 21. August 2020 13:59
    • Als Antwort markiert tim--97 Montag, 24. August 2020 08:31
    Freitag, 21. August 2020 13:54
  • Wie beschrieben, gegen eine Maschine ist es identisch, gegen mehrere kannst Du zwar auch einen Array von PSSession-Objekten übergeben, aber die musst Du dann erst mal alle erzeugen. Wenn man jede Session mehrmals benutzen möchte, macht es definitiv Sinn, sie einmal aufzubauen. Apropos: Die Sessions bitte am Ende explizit entfernen!

    Evgenij Smirnov

    http://evgenij.smirnov.de

    Freitag, 21. August 2020 14:45
  • Wie auch? Du füllst die Variablen im Inneren des Script-Blocks. Und nur da existieren sie. ;-)

     Vielen Dank für die Aufklärung!

    Ja so funktioniert es, dann auch.

    Montag, 24. August 2020 08:27
  • Ok, ich habe nun auch noch den den Remove-PSSession command eingebunden, danke für den Hinweis.

    Hier nun der funktionierende foreach Teil:

    foreach ($server in $servers)
    {
        Write-Output "Server: " $server.server
      
        $session = New-PSSession -ComputerName $server.server -Credential $c
    
        $systeminfo = 
        Invoke-Command -Session $session -ScriptBlock { 
            Get-CimInstance -ClassName win32_operatingsystem | 
                Select-Object csname, lastbootuptime
        }
    $systeminfo
    
        $gpresult = 
        Invoke-Command -Session $session -ScriptBlock { 
            gpresult /scope computer /r | findstr "SG_"
        }
    $gpresult
    
    Remove-PSSession -ComputerName $server.server
    
        "################   " + $systeminfo.csname +  "   ################" | Out-file -FilePath $resultsFolderPath -append
    $systeminfo | Out-file -FilePath $resultsFolderPath -append
    "GPRESULT: " | Out-file -FilePath $resultsFolderPath -append
    $gpresult | Out-file -FilePath $resultsFolderPath -append
    " " | Out-file -FilePath $resultsFolderPath -append
    "###########################################################" | Out-file -FilePath $resultsFolderPath -append
    " " | Out-file -FilePath $resultsFolderPath -append
    #Clear-Variable systeminfo, gpresult
    
       
    }


    • Als Antwort markiert tim--97 Montag, 24. August 2020 08:31
    Montag, 24. August 2020 08:31