trouble modifying ACL on a remote computer using Invoke-Command

This topic contains 6 replies, has 3 voices, and was last updated by  Don Jones 3 weeks, 3 days ago.

  • Author
    Posts
  • #78545

    Kevin Greer
    Participant

    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 
    
  • #78548

    Don Jones
    Keymaster

    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

  • #78554

    Kevin Greer
    Participant

    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 
    
  • #78557

    Don Jones
    Keymaster

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

    • #78563

      Liam Fisher
      Participant

      Or be dodgy and use $Args array 😛

  • #78578

    Kevin Greer
    Participant

    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
    
  • #78580

    Don Jones
    Keymaster

    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.

You must be logged in to reply to this topic.