Author Posts

August 31, 2017 at 1:52 pm

I'm having trouble running a script block on a remote computer using Invoke-Command. I can log into the remote computer and run the commands without a problem, I just cant figure out what I'm doing wrong with the invoke-command statement. I have tried using the -argumentlist parameter and I tried to add each line to its own invoke-command statement. Any help would be appreciated.

New-PSSession -ComputerName $FtpServer -Name 'FtpServer' -Credential $FtpCredentials | Out-Null
$Session = Get-PSSession -Name 'FtpServer'

$Username = SomeUser
$Permisison = 'FullControl'
$FtpFolderPath = 'E:\FtpFolder'
$FtpFolder = 'SomeFolder'

$scriptblock = 
{              
    $AcL = Get-ACL -Path "$FtpFolderPath\$FtpFolder"
    $Ar = New-Object System.Security.AccessControl.FileSystemAccessRule($UserName, $Permission, "ContainerInherit,ObjectInherit", None", "Allow")
    $Acl.SetAccessRule($Ar)
    Set-Acl -path "$FtpFolderPath\$FtpFolder" -AclObject $Acl
}

Invoke-Command -Session $Session -ScriptBlock $scriptblock 

August 31, 2017 at 1:55 pm

Your locally defined variables don't exist on the remote machine. So everything in the script block is null. -ArgumentList is PART of how you fix that, but you have to create a parameter block to receive those arguments.

See https://devops-collective-inc.gitbooks.io/the-big-book-of-powershell-gotchas/content/manuscript/remote-variables.html

August 31, 2017 at 2:18 pm

I used the $Using designator which seems to have done the trick. I previously tried using $args[0], $args[1], etc with the -argumentlist parameter with the variables comma separated. I'm not sure why I did not have luck with using -ArgumentList, but using $using is working!

Thank you!

$scriptblock = {
    $AcL = Get-ACL -Path $Using:invokePath
    $Ar = New-Object System.Security.AccessControl.FileSystemAccessRule($Using:UserName, $Using:Permission, "ContainerInherit,ObjectInherit", "None", "Allow")
    $Acl.SetAccessRule($Ar)
    Set-Acl -path $Using:invokePath -AclObject $Acl
}
Invoke-Command -Session $Session -ScriptBlock $scriptblock 

August 31, 2017 at 2:22 pm

With -ArgumentList you have to declare a Param() inside the script block to receive the arguments. But $using works too!

August 31, 2017 at 2:50 pm

Or be dodgy and use $Args array 😛

August 31, 2017 at 4:31 pm

So best practices... Use $using? What if the script block is just a single command? Use $using for any variables to pass or use -AgumentList? $Using looks like less typing and you don't have to keep track of the ArgumentList array.

Invoke-Command -ScriptBlock {Do-Something -Parameter $Using:Variable} 
Invoke-Command -ScriptBlock {Do-Something -Parameter $Args[0]} -ArgumentList $Variable

August 31, 2017 at 4:33 pm

The $args array is the worst practice, because it's hardest to read and interpret. A Param() block or $Using is best; $Using was introduced in v3, so it's only a problem if you need to work in v2.

Invoke-Command -ScriptBlock {Param($name,$address) Do-Something -Parameter $name} -ArgumentList $Variable1,$Variable2

That's the other option, wherein $Variable1 goes into $name and $Variable2 goes into $address. That ends up working well if you're using -FilePath instead of -ScriptBlock to send a parameterized script over the wire.