Make group of parameters mandatory - powershell

How can I make PowerShell script to accept 0 or 3 params? All or nothing.
[CmdletBinding()]
Param(
# Name of VPN connection
[Parameter(Mandatory=$False,ValueFromPipeline=$True,Position=1)]
[string]$vpn_name,
# Server URL or IP
[Parameter(Mandatory=$False,ValueFromPipeline=$True,Position=2)]
[string]$vpn_server,
# 192.168.72.0/24
[Parameter(Mandatory=$False,ValueFromPipeline=$True,Position=3)]
[string[]]$target_nets
)

try this
Param(
[Parameter(Mandatory=$True, Position=0, ParameterSet="FirstSet")]
[string]FirstRequiredParam,
[Parameter(Mandatory=$False, Position=0, ParameterSet="SecondSet")]
[string]FirstNotRequiredParam
)

Here is simplified snippet
[CmdletBinding()]
Param(
# Name of VPN connection
[Parameter(Mandatory=$True, ParameterSetName="WithParams")]
[string]$name,
# Server URL or IP
[Parameter(Mandatory=$True, ParameterSetName="WithParams"))]
[string]$vpn_server,
# No params
[Parameter(Mandatory=$False,ValueFromPipeline=$True,Position=0, ParameterSetName="NoParams")]
[string]$none
)
# Then check what parameters set was passed
switch ($PsCmdlet.ParameterSetName){
"WithParams" { Write-Host $name; break}
"NoParams" { Write-Host "No params passed."; break }
}

Related

Powershell [ValidateSet()] Between Separate Parameter Sets Using Same Parameter Name

OK, so I'm trying to write an advanced function that uses two different parameter set names, one is Default the other is TestAccountsOnly.
Most of this works fine, however, here's my problem:
The output of Get-Help New-SecondaryAccount gives me this in the SYNTAX section:
SYNTAX
New-SecondaryAccount [-Name] <String> [-AccountType] <String> [-Password] <String> [-Description] <String> [-OwnerEmployeeID] <String>
[[-AdditionalDescription]] [<CommonParameters>]
New-SecondaryAccount [-Name] <String> [-AccountType] <String> [-Password] <String> [-CoreOrReserved] <String> [-Description] <String>
[-OwnerEmployeeID] <String> [[-AdditionalDescription]] [<CommonParameters>]
From the looks of it, this is exactly what I want - one parameter set where I can validate a list of a handful of different -AccountTypes and move along where I have passwords, descriptions, etc., and the other where I validate just one value for AccountType and have a CoreOrReserve parameter that only belongs to the TestAccountsOnly parameter set.
Unfortunately, when trying to test this in the ISE, if I type:
New-SecondaryAccount -Name mehSomeAccount -AccountType, the only suggestion I get from IntelliSense is Test.
Can you not use [ValidateSet()] the way I'm trying to, or am I just doing it wrong?
Would really appreciate it if someone could point this out!
Function New-SecondaryAccount(DefaultParameterSetName="Default")
{
<#
.Synopsis
Creates a new secondary account based on the parameters
.DESCRIPTION
Creates a secondary AD user account based on parameters
specified. This includes several different types of accounts,
and determines the employeeType, OU, and description values
of the account created.
The CoreOrReserved parameter can only be used for accounts
where AccountType is set to Test
.INPUTS
[String]
.OUTPUTS
[ADObject]
.NOTES
.COMPONENT
MyModule_Part1
.FUNCTIONALITY
Active Directory Things
#>
[cmdletBinding(DefaultParameterSetName="Default")]
param(
[Parameter(Mandatory=$True,
Position=0,
ParameterSetName="Default",
ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$True)]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[Parameter(Mandatory=$True,
Position=0,
ParameterSetName="TestAccountsOnly",
ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$True)]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[String]$Name,
[Parameter(Mandatory=$True,
Position=1,
ParameterSetName="Default")]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[ValidateSet('ADAdmin','ServerAdmin','ServiceAccount','ChuckNorris')]
[Parameter(Mandatory=$True,
Position=1,
ParameterSetName="TestAccountsOnly")]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[ValidateSet("Test")]
[String]$AccountType,
[Parameter(Mandatory=$True,
Position=2,
ParameterSetName="Default")]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[ValidateScript(
{
if($_.Length -ge 12)
{
$True
}
else
{
throw "Password must be at least 12 characters"
$False
}
})]
[Parameter(Mandatory=$True,
Position=3,
ParameterSetName="TestAccountsOnly")]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[ValidateScript(
{
if($_.Length -ge 12)
{
$True
}
else
{
throw "Password must be at least 12 characters"
$False
}
})]
[String]$Password,
[Parameter(Mandatory=$True,
Position=2,
ParameterSetName="TestAccountsOnly")]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[ValidateSet("Core","Reserved")]
[String]$CoreOrReserved,
[Parameter(Mandatory=$True,
Position=3,
ParameterSetName="Default")]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[ValidateScript(
{
if($_ -match "^TASK\d{7}\b")
{
$True
}
else
{
throw "Description must be a TASK number only`nEx. TASK1234567"
$False
}
})]
[Parameter(Mandatory=$True,
Position=4,
ParameterSetName="TestAccountsOnly")]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[ValidateScript(
{
if($_ -match "^TASK\d{7}\b")
{
$True
}
else
{
throw "Description must be a TASK number only`nEx. TASK1234567"
$False
}
})]
[String]$Description,
[Parameter(Mandatory=$True,
Position=4,
ParameterSetName="Default")]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[ValidateScript(
{
if($(Get-ADUser -Filter {EmployeeID -eq $_ -and EmployeeType -eq "E"}) -ne $NULL)
{
$True
}
else
{
throw "$_ must correspond to a valid FTE user's employeeID number"
$False
}
})]
[Parameter(Mandatory=$True,
Position=5,
ParameterSetName="TestAccountsOnly")]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[ValidateScript(
{
if($(Get-ADUser -Filter {EmployeeID -eq $_ -and EmployeeType -eq "E"}) -ne $NULL)
{
$True
}
else
{
throw "$_ must correspond to a valid FTE user's employeeID number"
$False
}
})]
[String]$OwnerEmployeeID,
[Parameter(Mandatory=$False,
ParameterSetName="Default",
Position=5)]
[Parameter(Mandatory=$False,
ParameterSetName="TestAccountsOnly",
Position=6)]
[Switch]$AdditionalDescription
)
BEGIN{}
PROCESS{# implementation doing all the things here}
END{}
Unfortunately, you cannot declare more than one validate set attribute per parameter, which is one reason why its designation is separate.
You might be able to play around with dynamic parameters to get what you want. I stripped out a lot of stuff for clarity.
function New-SecondaryAccount() {
[cmdletBinding()]
param (
[Parameter(Mandatory,
Position = 0,
ValueFromPipeline,
ValueFromPipelineByPropertyName)]
[string] $Name,
[Parameter(Mandatory, Position = 1)]
[string] $Password,
[Parameter(Position = 2)]
[switch] $TestAccount
)
DynamicParam {
$attribute = New-Object System.Management.Automation.ParameterAttribute
$attribute.Mandatory = $true
$collection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
$collection.Add($attribute)
if ($TestAccount) {
$validationSet = #("Test")
} else {
$validationSet = #("ADAdmin", "ServerAdmin", "ServiceAccount", "ChuckNorris")
}
$collection.Add((New-Object System.Management.Automation.ValidateSetAttribute($validationSet)))
$param = New-Object System.Management.Automation.RuntimeDefinedParameter('AccountType', [string], $collection)
$dictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
$dictionary.Add('AccountType', $param)
return $dictionary
}
PROCESS {
<# implementation doing all the things here #>
}
}

Parameter sets - ensure parameters exist

I'm trying to use Parameter Sets to replicate this functionality:
if (($hostName) -or ($databaseName) -and (!$databasePassword)) {
throw "If hostName or databaseName specified, you must use databasePassword parameter."
}
Simple example of what I have so far:
[Parameter(Mandatory=$false, ParameterSetName="Test")]
[string]$hostName,
[Parameter(Mandatory=$false, ParameterSetName="Test")]
[string]$databaseName,
[Parameter(Mandatory=$false, ParameterSetName="Test")]
[string]$databasePassword
This is not working. I can supply $hostName without $databasePassword for example, or $dataBasename without $databasePassword and the function runs.
What am I missing?
Make two parameter sets, make $Hostname mandatory in the first, make $DatabaseName optional in the first and mandatory in the other, make $DatabasePassword mandatory in both.
[CmdletBinding(DefaultParameterSetName='host')]
Param(
[Parameter(ParameterSetName='host', Mandatory=$true)]
[string]$Hostname,
[Parameter(ParameterSetName='host', Mandatory=$false)]
[Parameter(ParameterSetName='dbname', Mandatory=$true)]
[string]$DatabaseName,
[Parameter(ParameterSetName='host', Mandatory=$true)]
[Parameter(ParameterSetName='dbname', Mandatory=$true)]
[string]$DatabasePassword
)
Set databasePassword to be mandatory?
[Parameter(Mandatory=$true, ParameterSetName="Test")]
[string]$databasePassword

How to specify a required parameter only if an optional switch is used

I am processing CSV files to insert a column. If the file has a header record of field names (-hasheader), then I also need a column name (-new_label) value.
I put both of these parameters into a parameter set, but -new_label should not be required if -hasheader is not used. How can I cause -new_label to not be required unless -hasheader is used? Is this where DynamicParam must be used?
[cmdletbinding()]
Param(
[Parameter(Mandatory=$true, position=0)]
[string]$csv_in
,[Parameter(Mandatory=$true, position=1)]
[string]$csv_out
,[Parameter(Mandatory=$true, position=2)]
[string]$column
,[Parameter(Mandatory=$true, position=3)]
[string]$new_value
,[Parameter(Mandatory=$false, ParameterSetName="HeaderRecord")]
[switch]$hasheader
,[Parameter(Mandatory=$true, ParameterSetName="HeaderRecord")]
[string]$new_label
,[Parameter(Mandatory=$false)]
[string]$delimiter = ','
,[Parameter(Mandatory=$false)]
[string]$quote = '"'
)
I also tried the following. PowerShell did not complain about the Mandatory value being a script block, but it still required the new_label parameter.
,[Parameter(Mandatory={$hasheader -eq $true}, ParameterSetName="HeaderRecord")]
Make the default parameter set something other than HeaderRecord:
[CmdletBinding(DefaultParameterSetName='foo')]
Param(
[Parameter(Mandatory=$true, Position=0)]
[string]$csv_in,
[Parameter(Mandatory=$true, Position=1)]
[string]$csv_out,
[Parameter(Mandatory=$true, Position=2)]
[string]$column,
[Parameter(Mandatory=$true, Position=3)]
[string]$new_value,
[Parameter(Mandatory=$false, ParameterSetName="HeaderRecord")]
[switch]$hasheader,
[Parameter(Mandatory=$true, ParameterSetName="HeaderRecord")]
[string]$new_label,
[Parameter(Mandatory=$false)]
[string]$delimiter = ',',
[Parameter(Mandatory=$false)]
[string]$quote = '"'
)

Need help writing if statement in PowerShell

So I have this script that creates a snap mirror on our dr server based on its location. Below is just a small part of a the script. I need to write an if statement so if location='uk' then to not run the below function otherwise if location='us' then create snap-mirror.
function Create-SnapMirror {
[CmdletBinding(PositionalBinding=$false,
HelpUri='http://www.microsoft.com/',
ConfirmImpact='Medium')]
[OutputType([Boolean])]
Param(
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
ValueFromRemainingArguments=$false,
Position=0)]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[String]$SourcePath,
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
ValueFromRemainingArguments=$false,
Position=1)]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[String]$DestinationPath,
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
ValueFromRemainingArguments=$false,
Position=2)]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[String]$LogName
)
$success = $null
$error.Clear()
}
Assuming that the logic is required outside of the function you can achieve this by simply encapsulating the function call within the if statement as follows:
if($Location -eq 'us') { Create-SnapMirror -SourcePath $MySourcePath -DestinationPath $MyDestinationPath -LogName $MyLogName }
If however you want to check the location within the function you will first need to receive the location either from the input parameters or some other method. Assuming that you have the location in a variable named $Location you can simply add the following within your function before any other action:
if($Location -ne 'us') { return }
This will exit the function; you can add other actions, for instance logging within the parenthesis.

Auto complete values of the parameters powershell

I am trying to find the way to create values for parameters that can be auto completed or show all available options with tab, like the value "allsigned" in the cmdlet
Set-ExecutionPolicy -ExecutionPolicy AllSigned
¿Any ideas about how this is called in programation or how can I achieve this ?
yes its called validateset
Param
(
[parameter(Mandatory=$true)]
[ValidateSet("Low", "Average", "High")]
[String[]]
$Detail
)
advanced functions/cmdlets or just parameter validation, parameter sets, etc
snippet from the ISE:
function Verb-Noun
{
[CmdletBinding(DefaultParameterSetName='Parameter Set 1',
SupportsShouldProcess=$true,
PositionalBinding=$false,
HelpUri = 'http://www.microsoft.com/',
ConfirmImpact='Medium')]
[Alias()]
[OutputType([String])]
Param
(
# Param1 help description
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
ValueFromRemainingArguments=$false,
Position=0,
ParameterSetName='Parameter Set 1')]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[ValidateCount(0,5)]
[ValidateSet("sun", "moon", "earth")]
[Alias("p1")]
$Param1,
# Param2 help description
[Parameter(ParameterSetName='Parameter Set 1')]
[AllowNull()]
[AllowEmptyCollection()]
[AllowEmptyString()]
[ValidateScript({$true})]
[ValidateRange(0,5)]
[int]
$Param2,
# Param3 help description
[Parameter(ParameterSetName='Another Parameter Set')]
[ValidatePattern("[a-z]*")]
[ValidateLength(0,15)]
[String]
$Param3
)
Begin
{
}
Process
{
if ($pscmdlet.ShouldProcess("Target", "Operation"))
{
}
}
End
{
}
}