Search code examples
arrayspowershellacl

Powershell Set-Acl - Error New-Object : Cannot find an overload for "FileSystemAccessRule" and the argument count: "1"


I'm using the following array to apply permissions to directories but get the error:

New-Object : Cannot find an overload for "FileSystemAccessRule" and the argument count: "1".

$psarray = @(
    ('xppusers', 'D:\XPP\xz\bin', 'Read'),
    ('xppusers', 'D:\XPP\xz\sys\config', 'Read'),
    ('xppusers', 'D:\XPP\sd_liz', 'Read'),
    ('xppusers', 'D:\XPP\xz\help', 'Read')
)


foreach($item in $psarray)
{
    $permission = "'" + $item[0] + "', '" + $item[2] + "', 'ContainerInherit, ObjectInherit', 'None', 'Allow'"
    $rule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $permission
    $acl.SetAccessRule($rule)
    $acl | Set-Acl -Path $item[1]
}

And the full error is:

New-Object : Cannot find an overload for "FileSystemAccessRule" and the argument count: "1".
At C:\GPO-Installers\permissions-array.ps1:20 char:13
+     $rule = New-Object -TypeName System.Security.AccessControl.FileSy ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [New-Object], MethodException
    + FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand

If I create the $permission manually it works fine.

eg:

$permission = 'xppusers', 'read', 'ContainerInherit, ObjectInherit', 'None', 'Allow'

Not sure where I have gone wrong and would really appreciate some help.

Thanks.

EDIT:

Thanks to @mklement0 I've fiddled this and got it working. At some stage when the pressure is off I will go back and understand this properly rather than just copy/pasta my way through the issue.

I've got this working by creating the required variables within the foreach loop and then using these in the New-Object.

foreach($item in $UserGroupPermissionArray)
    {     
        $UserGroup = $item[0]
        $Path = $item[1]
        $acl = Get-Acl -Path $Path
        $FileSystemRights = $item[2]
        $InheritanceFlag = "ContainerInherit"
        $PropagationFlag = "None"
        $AccessControlType = "Allow"
        $rule = New-Object System.Security.AccessControl.FileSystemAccessRule ($UserGroup, $FileSystemRights, $InheritanceFlag, $PropagationFlag, $AccessControlType)
        $acl.SetAccessRule($rule)
        $acl | Set-Acl -Path $Path
    }

Solution

  • You're mistakenly passing a single string to the System.Security.AccessControl.FileSystemAccessRule constructor (via New-Object -ArgumentList); the error implies that there is no constructor (overload) that takes a single argument of type [string].[1]

    Instead, you must pass constructor arguments individually, which in the context of New-Object means as an array (-Args is an alias for -ArgumentList, and you could even omit the -Args):

    $rule = New-Object System.Security.AccessControl.FileSystemAccessRule `
              -Args ($item + 'ContainerInherit, ObjectInherit', 'None', 'Allow')
    

    Since $item is an array containing the first 2 constructor arguments, you can simply use array concatenation (+) to append[2] the invariant arguments.


    [1] The error message can situationally be misleading, since it doesn't explicitly state that it isn't only the count of arguments that matters, but also the argument's data type. For instance, you'd see the same message if there were a single-argument constructor, but its argument type were something other than [string].

    [2] Technically, a new array is created that is the concatenation of the elements from the input arrays.