Reputation: 14705
I'm having some issues with defining the position of parameters. For example, when I pipe a $Folder
to my function, the positions of the other parameters change.
Normally the paramter $Folder
has position=0
, but when something is piped to the function it's not taking into account that position 0 is before the pipeline symbol an no longer behind it.
The function can be used in all cases with or without the switch $Recurse
and the $Inheritance
set to On/Off
. The main purpose is to set permissions or to set the inheritance on a folder. A combination of both is also possible.
[CmdletBinding(SupportsShouldProcess=$True,DefaultParametersetName="SetPermissions")]
Param(
[parameter(Mandatory=$true,ValueFromPipeline=$true,Position=0)]
[ValidateNotNullOrEmpty()]
[ValidateScript({Test-Path $_ -PathType Container})]
[String[]]$Folder,
[parameter(Mandatory=$true,Position=1,ParameterSetName='SetPermissions')]
[parameter(Mandatory=$false,ParameterSetName='SetInheritance')]
[ValidateNotNullOrEmpty()]
[String]$SAMaccountName,
[parameter(Mandatory=$true,Position=2,ParameterSetName='SetPermissions')]
[parameter(Mandatory=$false,ParameterSetName='SetInheritance')]
[ValidateNotNullOrEmpty()]
[ValidateSet('ReadAndExecute','Modify','FullControl','ListFolderContents')]
[String]$Grant,
[parameter(Mandatory=$false)]
[ValidateNotNullOrEmpty()]
[String]$Domain = 'MyDomain',
[parameter(Mandatory=$false,Position=3,ParameterSetName='SetPermissions')]
[parameter(Mandatory=$true,Position=1,ParameterSetName='SetInheritance')]
[ValidateNotNullOrEmpty()]
[ValidateSet('On','Off')]
[String]$Inheritance,
[Switch]$Recurse
)
All the options that are possible:
# SetPermissions
Set-ACLspecial -Folder 'C:\Folder' -SAMaccountName 'Bob' -Grant ReadAndExecute
Set-ACLspecial -Folder 'C:\Folder' -SAMaccountName 'Bob' -Grant ReadAndExecute -Recurse
Set-ACLspecial -Folder 'C:\Folder' -SAMaccountName 'Bob' -Grant ReadAndExecute -Inheritance On
Set-ACLspecial -Folder 'C:\Folder' -SAMaccountName 'Bob' -Grant ReadAndExecute -Inheritance On -Recurse
Set-ACLspecial 'C:\Folder' 'Bob' ReadAndExecute
Set-ACLspecial 'C:\Folder' 'Bob' ReadAndExecute -Recurse
Set-ACLspecial 'C:\Folder' 'Bob' ReadAndExecute On
Set-ACLspecial 'C:\Folder' 'Bob' ReadAndExecute On -Recurse
'C:\Folder' | Set-ACLspecial 'Bob' ReadAndExecute
'C:\Folder' | Set-ACLspecial 'Bob' ReadAndExecute -Recurse
'C:\Folder' | Set-ACLspecial 'Bob' ReadAndExecute On
'C:\Folder' | Set-ACLspecial 'Bob' ReadAndExecute On -Recurse
# SetInheritance
Set-ACLspecial 'C:\Folder' -Inheritance Off
Set-ACLspecial 'C:\Folder' -Inheritance Off -Recurse
'C:\Folder' | Set-ACLspecial -Inheritance Off
'C:\Folder' | Set-ACLspecial -Inheritance Off -Recurse
The current syntax:
Set-HCaclTEST [-Folder] <String[]> [-SAMaccountName] <String> [-Grant] <String> [-Domain <String>] [[-Inheritance] <String>] [-Recurse] [-WhatIf] [-Confirm] [<Common
Parameters>]
Set-HCaclTEST [-Folder] <String[]> [-SAMaccountName <String>] [-Grant <String>] [-Domain <String>] [-Inheritance] <String> [-Recurse] [-WhatIf] [-Confirm] [<CommonPa
rameters>]
The error:
'C:\Folder' | Set-ACLspecial 'Bob' ReadAndExecute
# Test-Path on 'Bob' is not working... PowerShell sees Bob as the variable `$Folder`, but it's not.
Upvotes: 2
Views: 3651
Reputation: 46710
Hopefull you can use this to follow the logic used in parameter binding. Its an excerpt from Windows Powershell in Action
By Bruce Payette.
Following this I hope you can determine what is happening, and in what order, with your routine.
In the example 'C:\Folder' | Set-ACLspecial 'Bob' ReadAndExecute
'Bob'
should be assigned to $Folder
since positional is bound before pipeline.
Upvotes: 2
Reputation: 26749
The Position
value is only used to match unnamed parameters. Parameters passed via a pipeline are named, so are ignored when doing this calculation. In your example, the first unnamed parameter is Bob
, so that gets assigned to parameter $Folder
, because that parameter's position is 0
. Best practice is to always use parameter names in your scripts. It makes them easier to understand. Use positional parameters when on the console to save yourself keystrokes.
From what I've seen in the PowerShell base cmdlets, parameters that take pipeline input usually aren't also positional. (Probably for just this reason.) Parameters that can be piped in must be passed by name when not passed via the pipeline. Remove Position=0
from the $Folder
parameter.
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
[ValidateNotNullOrEmpty()]
[ValidateScript({Test-Path $_ -PathType Container})]
[String[]]
$Folder,
Upvotes: 6