Search code examples
powershellscriptingremote-serverhyper-v

Powershell Hyper-V remote execution receives no response


I have a work machine(A) and a different Hyper-V server (B) with virtual machines running.

If I connect to the Hyper-V server B with RDP and run Get-VM Where-Object {$_.State -eq 'Running'} I get a valid answer:

Name          State   CPUUsage(%) MemoryAssigned(M) Uptime     Status
----          -----   ----------- ----------------- ------     ------
vm1           Running 2           2048              20:07:05   Operating normally
vm2           Running 0           1024              3.00:49:30 Operating normally

Next, I wrote a PS script to run on my work machine A:

$sess = New-PSSession $SETTING_SESSION_HOST
$commandStr = "Get-VM | Where-Object { `$_.State -eq 'Running' }"
#or a simple version: $commandStr = "Get-VM"
[console]::writeline("Executing: [{0}]", $commandStr)

$commandBlock = [scriptblock]::Create($commandStr)
$job = Invoke-Command -Session $sess -ScriptBlock $commandBlock -AsJob
Wait-Job $job
$vml = Receive-Job $job

foreach($m in $vml)
{
    [console]::writeline("Executing: [{0}]", $m.Name)
}

$g = Format-List -InputObject $vml
[console]::writeline("format list: [{0}]", $g)

Here I would expect to see 2 lines containing "vm1" and "vm2" respectively. But I get an empty response:

Executing: [Get-VM | Where-Object { $_.State -eq 'Running' }]
format list: []

Any idea on how to get remote response from remote job? Also, the execution time of the script is ~6 seconds (all spent in Wait-Job), while on the server it runs instantaneously.

EDIT: added -AsJob parameter EDIT: fixed variables


Solution

  • After doing some debugging, I found the answer: when there's only 1 machine running, then the return result is an object of type Microsoft.HyperV.PowerShell.VirtualMachine, so this code works nicely:

    $vml = Invoke-Command -Session $sess -ScriptBlock {Get-VM | where State -eq 'Running'}
    $vml.Name
    

    However, if there are more than 1 machine running, then the result is Object[], and the code I found out working is like this:

    $vml = Invoke-Command -Session $sess -ScriptBlock {Get-VM | where State -eq 'Running'}
    $len = $vml.length
    if ($len)
    {
        [console]::writeline("Machine count: [{0}]", $len)
        for ($i=0; $i -lt $len; $i++)
        {
            $m = $vml[$i]
            [console]::writeline("machine: [{0}]", $m.Name)
        }
    }
    else
    {
        [console]::writeline("Machine: [{0}]", $vml.Name)
    }
    

    Note that doing a foreach($m in $vml) doesn't seem to work for some reason.

    The problem in my opinion is that the method is either returning an object or an array.