0

I need output of variable from Invoke-Command, but when printing it is showing empty, below is the sample code:

$ServiceName = "Service"

Invoke-Command -ScriptBlock {

        try {
            iisreset
            $BodyContent += "Server: <b>$server</b> IIS reset completed<br>"

        }
        catch {
            $BodyContent += "Server: <b>$server</b> is Failed to restart IIS<br>"
            $ErrorStat = 1
        }

        try {
            Stop-Service -DisplayName $using:ServiceName
            $BodyContent += "Server: <b>$server</b> is successfully Stopped $using:ServiceName<br>"
        }
        catch {
            $BodyContent += "Server: <b>$server</b> is failed to Stop $using:ServiceName<br>"
            $ErrorStat = 1
        }

        try {
            Start-Service -DisplayName $using:ServiceName
            $BodyContent += "Server: <b>$server</b> is successfully Started $using:ServiceName<br>"
        }
        catch {
            $BodyContent += "Server: <b>$server</b> is failed to Start $using:ServiceName<br>"
            $ErrorStat = 1
        }

    } -ComputerName $server -Credential $user -ErrorAction Stop

Here, I want to capture $BodyContent and $ErrorStat

Clijsters
  • 4,031
  • 1
  • 27
  • 37
San
  • 226
  • 5
  • 14
  • Possible duplicate of [How to capture the Return Value of a ScriptBlock invoked with Powershell's Invoke-Command](https://stackoverflow.com/questions/8549184/how-to-capture-the-return-value-of-a-scriptblock-invoked-with-powershells-invok) – gvee Mar 19 '18 at 11:14

2 Answers2

1

Invoke-Command returns to you what is printed to the end of the pipeline. If you want to return a variable you should Return <variable> like:

$ret = Invoke-Command -ScriptBlock { $var="test string"; return $var; }

where $ret contains now the value test string.

When you got multiple variables you want to return, then you can join them into a single variable, e.g. like this:

$str1 = "test"
$str2 = "123"
$combinedObjs = New-Object PSObject -Property @{1 = $str1; 2 = $str2}

Now you can combine it all

$ret = Invoke-Command -ScriptBlock { 
  $str1 = "test";
  $str2 = "123";
  $combinedObjs =  @{val1 = $str1; val2 = $str2};
  Return $combinedObjs;
}

now $ret contains

Name                           Value
----                           -----
val1                           test
val2                           123

and you can access them by calling $ret.val1 or $ret.val2

Clijsters
  • 4,031
  • 1
  • 27
  • 37
kim
  • 3,385
  • 2
  • 15
  • 21
  • I'd say _what is printed to the screen_ is not accurate. – Clijsters Mar 19 '18 at 11:24
  • Updated my text. That was bad wording from my side – kim Mar 19 '18 at 11:27
  • Perfect! I suggested an edit, but this is now overriden by yours, which is Ok. I would just remove the quote marks from the inline code blocks, as they are - syntactically - not a part of the value, but this is kind of me going to be petty ;) – Clijsters Mar 19 '18 at 11:29
0

Add some output to the very end of given scriptblock, e.g.

    @{  BodyContent = $BodyContent
        ErrorStat   = $ErrorStat
    }

If you use e.g.

$result = Invoke-Command -ScriptBlock { 

    ###  original script block body here

    @{  BodyContent = $BodyContent
        ErrorStat   = $ErrorStat
    }
}  -ComputerName $server -Credential $user -ErrorAction Stop

then you can check

$result.BodyContent
$result.ErrorStat
JosefZ
  • 28,460
  • 5
  • 44
  • 83