Dmitry Dorofeev
Dmitry Dorofeev

Reputation: 85

Can't assign value to a variable inside of Invoke-Command

It seems to be strange but I can't assign a value to variable inside of Invoke-Command. Here is the code below but when print out $targetComputerPath it's simply empty. What's wrong?

foreach ($item in $computersPath){

    $computername = $item.Name
    $username = $item.UserID

    Write-Host computer $computername and user $username

    if (Test-Connection -ComputerName $computername -Count 1 -ErrorAction SilentlyContinue)
    {
        if ($((Get-Service WinRM -ComputerName $computername).Status) -eq "stopped")
        {
          (Get-Service WinRM -ComputerName $computername).Start()
        } 
        Invoke-Command -ComputerName $computername -ScriptBlock {

        if ($((Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").ReleaseId) -eq "1903" ) 
            {
               $targetComputerPath = "\\"+$computername+"\c$\Users\"+$username+"\Desktop\"
               write-host "1903"
            } 
        else 
            {
              $targetComputerPath = "\\"+$computername+"\c$\Users\"+$username+"\Desktop\"
              write-host "something else"
            } 
        }
    }
    write-host $targetComputerPath
}

Upvotes: 1

Views: 704

Answers (1)

Tomalak
Tomalak

Reputation: 338406

The point of WinRM is that you take a script block, and execute it on a different machine.

None of the variables you define in the host script will be available on the remote machine.

This becomes more apparent when you separate the "task", a.k.a the script block, from the Invoke-Command, like this:

$task = {
    $version = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion"
    if ($version.ReleaseId -eq "1903") {
        # note that `$username` cannot be available here, it's never been defined!
        return "\\$env:COMPUTERNAME\c$\Users\$username\Desktop"
    } else {
        return "\\$env:COMPUTERNAME\c$\Users\$username\Desktop"
    } 
}

foreach ($item in $computersPath) {
    $computername = $item.Name
    $username = $item.UserID

    Write-Host computer $computername and user $username

    if (Test-Connection -ComputerName $computername -Count 1 -ErrorAction SilentlyContinue) {
        $winrm = Get-Service WinRM -ComputerName $computername
        if ($winrm.Status -eq "stopped") { $winrm.Start() }
        $targetComputerPath = Invoke-Command -ComputerName $computername -ScriptBlock $task
        Write-Host "The machine returned: $targetComputerPath"
    }
}

As you can see, you can return values from the script block and they will be available as the return value of Invoke-Command.

If you want to pass arguments to your script block, this thread talks about that: How do I pass named parameters with Invoke-Command?

Upvotes: 2

Related Questions