marcimarc85
Goto Top

Powershell Invoke-Command Fehler

Hallo,

Ich habe ein Powershell Script, was ich gern für unser PRT Monitoring nutzen möchte. Mit dem Script kann ich die Erreichbarkeit eines Ports auf einem Remote_Server prüfen und in PRTG als Sensor darstelen. Das klappt soweit auch.

Nur muss ich das Script noch so anpassen, dass ich die Verbindung mehrerer QuellServer zu einem bestimmten Zielserver-Port abfragen kann.

Das ganze wollte ich mit Invoke Command realisieren, aber ich bekomme immer den Fehler

S D:\railsys\3rdparty\mysql-5.7.17-winx64\bin>

remote_port_check.ps1 administrator password 10.32.12.116 10.32.6.50 27009
Cannot validate argument on parameter 'Port'. The 0 argument is less than the minimum allowed range of 1. Supply an argument that is greater than or equal to 1 and then try the command again.  
At D:\railsys\enterprise\bin\powershell_tools\remote_port_check3.ps1:16 char:1
+ Invoke-Command  -ComputerName $SourceServer -Credential $credentials -ErrorActio ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Test-NetConnection], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Test-NetConnection
    + PSComputerName        : 10.32.12.116

und so sieht das Script aus:

param (
[Parameter(Mandatory=$true)][String]$adminusername,
[Parameter(Mandatory=$true)][String]$adminpassword,
[Parameter(Mandatory=$true)][String]$SourceServer,
[Parameter(Mandatory=$true)][String]$DestinationServer,
[Parameter(Mandatory=$true)][String]$port
)


################################# Network Credentials #######################################
$password = ConvertTo-SecureString $adminpassword -AsPlainText -Force
$credentials = New-Object System.Management.Automation.PSCredential($adminusername,$password)
#############################################################################################


Invoke-Command  -ComputerName $SourceServer -Credential $credentials -ErrorAction Stop -ScriptBlock{param($DestinationServer,$port)
$porttest=Test-NetConnection -ComputerName $DestinationServer -Port $port
$port_result=($porttest).RemotePort
$server_result=($porttest).ComputerName

if (($porttest).TcpTestSucceeded -eq 'True') {  
$result="[Success] Port $port_result at server $server_result is reachable."  
$result_value="0"  

} else {
$result="[Failed] Port $port at server $server_result is not reachable."  
$result_value="1"  
} 

}


write-host "<prtg>"  
Write-Host "<result>"  
Write-Host "<channel>Port $($port)</channel>"  
Write-Host "<value>$($result_value)</value>"  
Write-Host "</result>"  
Write-Host "<text> $($result) </text>"  
write-host "</prtg>"  



$postParams = "<prtg><result><channel>Port $($port)</channel><value>$($result_value)</value></result><text>$($result) </text></prtg>"  

Content-ID: 7747389332

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

Ausgedruckt am: 22.11.2024 um 05:11 Uhr

5388706050
5388706050 05.07.2023 um 09:52:07 Uhr
Goto Top
Moin,

ich hätte im nächsten Versuch mal den PARAM-Teil im Scriptblock (Zeile 16) weggelassen. Du müsstest innerhalb des Scriptblocks auch so auf die „äußeren“ Variablen zugreifen können. Ist nur ein Schuss ins Blaue - nicht validiert oder so…

Viel Erfolg
NULL
7426148943
Lösung 7426148943 05.07.2023 aktualisiert um 10:10:33 Uhr
Goto Top
Variablen außerhalb des Invoke-Command Scriptblocks werden nicht automatisch an den
Invoke-Command Scriptblock weitergegeben, dieser wird ja Remote in einer neuen Session ausgeführt, dazu musst du entweder Invoke-Command diese mit dem Parameter -Argumentlist mitgeben oder diese im Block direkt ansprechen mittels $using: Prefix
$using:Port
$using:DestinationServer
Das param() kann dann entfallen.

https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell ...
$using: - Used to access variables defined in another scope while running scripts via cmdlets like Start-Job and Invoke-Command.

Zeppel
MarciMarc85
MarciMarc85 05.07.2023 um 10:52:55 Uhr
Goto Top
Zitat von @7426148943:

Variablen außerhalb des Invoke-Command Scriptblocks werden nicht automatisch an den
Invoke-Command Scriptblock weitergegeben, dieser wird ja Remote in einer neuen Session ausgeführt, dazu musst du entweder Invoke-Command diese mit dem Parameter -Argumentlist mitgeben oder diese im Block direkt ansprechen mittels $using: Prefix
$using:Port
$using:DestinationServer
Das param() kann dann entfallen.

https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell ...
$using: - Used to access variables defined in another scope while running scripts via cmdlets like Start-Job and Invoke-Command.

Zeppel

Vielen Danl Zeppel! Das war ja einfacher als gedacht face-smile
MarciMarc85
MarciMarc85 05.07.2023 um 11:38:17 Uhr
Goto Top
@ze
Zitat von @7426148943:

Variablen außerhalb des Invoke-Command Scriptblocks werden nicht automatisch an den
Invoke-Command Scriptblock weitergegeben, dieser wird ja Remote in einer neuen Session ausgeführt, dazu musst du entweder Invoke-Command diese mit dem Parameter -Argumentlist mitgeben oder diese im Block direkt ansprechen mittels $using: Prefix
$using:Port
$using:DestinationServer
Das param() kann dann entfallen.

https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell ...
$using: - Used to access variables defined in another scope while running scripts via cmdlets like Start-Job and Invoke-Command.

Zeppel

Nachtrag: Variablen für $result und $result_value werden nun allerdings aus dem Invoke-Command an den write-host Bereich übergeben. dort bleiben die Werte nun leer, bis auf $Port, da ich den ja auch in den Parametern am Anfang schon mitgebe.
Ich kann die schließende Klammer auch ganz ans ende setzten, dann werden die write-host Ausgaben in Powershell direkt auch korrekt ausgegeben, aber das PRTG Monitoring kann damit dann nicht mehr umgehen:

"XML: Das zurückgelieferte XML entspricht nicht dem erwarteten Schema. (Code: PE233) -- JSON: Das zurückgelieferte JSON entspricht nicht der erwarteten Struktur (No mapping for the Unicode character exists in the target multi-byte code page). (Code: PE231)"
7426148943
7426148943 05.07.2023 aktualisiert um 11:58:22 Uhr
Goto Top
Write-host ist ja auch Blödsinn das gibt nichts zurück wenn dann "out-host".
Oder direkt auageben, write-host ist nur fürs Auge aber nicht um etwas aus einem Skript zurückzugeben ... Noch viel lernen du musst mein lieber Padawan. 😉
MarciMarc85
MarciMarc85 05.07.2023 um 13:03:36 Uhr
Goto Top
Zitat von @7426148943:

Write-host ist ja auch Blödsinn das gibt nichts zurück wenn dann "out-host".
Oder direkt auageben, write-host ist nur fürs Auge aber nicht um etwas aus einem Skript zurückzugeben ... Noch viel lernen du musst mein lieber Padawan. 😉

Das ist aber nunmal das Format, das PRTG erwartet für die Auswertung:

kb.paessler.com/en/topic/43123-powershell-commands-to-custom-sensor
7426148943
7426148943 05.07.2023 aktualisiert um 16:01:48 Uhr
Goto Top
Ist aber uggly ...

param (
    [Parameter(Mandatory=$true)][String]$adminusername,
    [Parameter(Mandatory=$true)][String]$adminpassword,
    [Parameter(Mandatory=$true)][String]$SourceServer,
    [Parameter(Mandatory=$true)][String]$DestinationServer,
    [Parameter(Mandatory=$true)][String]$port
)

################################# Network Credentials #######################################
$credentials = [PSCredential]::new($adminusername,(ConvertTo-SecureString $adminpassword -AsPlainText -Force))
#############################################################################################


$result = Invoke-Command  -ComputerName $SourceServer -Credential $credentials -ErrorAction Stop -ScriptBlock {
    $porttest = Test-NetConnection -ComputerName $using:DestinationServer -Port $using:port
    $port_result = $porttest.RemotePort
    $server_result = $porttest.ComputerName
    if ($porttest.TcpTestSucceeded -eq 'True') {    
        [pscustomobject]@{
            message = "[Success] Port $port_result at server $server_result is reachable."  
            value = 0
        }
    } else {
        [pscustomobject]@{
            message = "[Failed] Port $port at server $server_result is not reachable."  
            value = 1
        }
    }
}

@"  
<?xml version="1.0" encoding="UTF-8" ?>  
<prtg>
    <result>
        <channel>Port $port</channel>
        <value>$($result.value)</value>  
    </result>
    <text>$($result.message)</text>
</prtg>"  
"@  
MarciMarc85
MarciMarc85 06.07.2023 aktualisiert um 08:48:07 Uhr
Goto Top
Soooo... Im Prinzip funktionierte das Script schon, wie im ersten Post bzw. nach deiner ersten Antwort. Das Problem war nur, dass ich das Script nicht direkt vom Monitoring Server ausgeführt hatte, sondern von einem Testsystem, wo ich es erstellt hab. Da funktionierte es problemlos, also bin ich davon ausgegangen, dass es das überall anders auch tut.

Das Problem ist aber, dass das Script ja die Verbindung von server A auf Server B prüft. Dazu war es notwendig folgenden Befehl in Powershell vorab auszuführen:

Set-Item WSMan:\localhost\Client\TrustedHosts -Value *