12

I'm trying to retrieve the hash of a file located on remote server using Invoke-Command. It works fine when I give the full path as below:

Invoke-Command -ComputerName winserver -ScriptBlock { 
    Get-FileHash -Path E:\test\testfile.zip -Algorithm SHA1 
}

But I need to pass the file name via a variable as below:

Invoke-Command -ComputerName winserver -ScriptBlock { 
    Get-FileHash -Path "E:\test\$dest.zip" -Algorithm SHA1 
}

How do I access this variable in the scriptblock of a remote session?

Maximilian Burszley
  • 18,243
  • 4
  • 34
  • 63
Bose
  • 143
  • 1
  • 2
  • 10

2 Answers2

25

In PowerShell 4 (3+ actually) the easiest way is to use the Using scope modifier:

Invoke-Command -ComputerName winserver -ScriptBlock { 
    Get-FileHash E:\test\$Using:dest.zip -Algorithm SHA1 
}

For a solution that works with all versions:

Invoke-Command -ComputerName winserver -ScriptBlock {
    param($myDest)

    Get-FileHash E:\test\$myDest.zip -Algorithm SHA1 
} -ArgumentList $dest
Maximilian Burszley
  • 18,243
  • 4
  • 34
  • 63
briantist
  • 45,546
  • 6
  • 82
  • 127
11

To complement briantist's helpful answer:

The script block passed to Invoke-Command is (as intended) executed on the remote machine, using the remote machine's variables by default.

Thus, in order to use a local variable's value,[1] extra steps are needed (to put it differently: inside a script block executed remotely, you cannot just refer to local variables as you normally would, such as with $dest):

  • PS v3+ offers the using: scope modifier for direct use of a local variable's value inside the script block - see briantist's first command.

    • Note that using: only works when Invoke-Command actually targets a remote machine, such as with the -ComputerName parameter.
  • The only option that also works in earlier versions is to pass the local variable as a parameter to the script block. - see briantist's second command.

As an aside:

  • Because the local variable values undergo serialization, due to the remote script block by definition running out of process, type fidelity is limited, though .NET primitive types and strings are not affected - see this answer for details.

[1] Note that you fundamentally cannot pass a variable itself, only its value; that is, you cannot assign to a local variable in a remote script block.

mklement0
  • 382,024
  • 64
  • 607
  • 775