Applying an attribute to all parameters - powershell

I've got the following list of parameters for a SQL script. They're all mandatory, as you can see.
param(
[Parameter(Mandatory)][string]$dropLoc,
[Parameter(Mandatory)][string]$manifest,
[Parameter(Mandatory)][string]$accountName,
[Parameter(Mandatory)][string]$appSqlServer,
[Parameter(Mandatory)][string]$appDatabaseName,
[Parameter(Mandatory)][string]$oltpDatabaseName,
[Parameter(Mandatory)][string]$oltpSqlServerName,
[Parameter(Mandatory)][string]$appRootURL,
[Parameter(Mandatory)][string]$AppServiceDBKey,
[Parameter(Mandatory)][string]$reportDBSqlServerName,
[Parameter(Mandatory)][string]$udmInstanceName,
[Parameter(Mandatory)][string]$reportDBDataPath,
[Parameter(Mandatory)][string]$reportDBLogPath,
[Parameter(Mandatory)][string]$maxETL
)
But this is really lengthy and I don't like how I set each one mandatory individually. Does Powershell have a way to set an attribute to all parameters?

Related

Param in CmdletBinding not mandatory and error/misspelled checking

Hey all I have a powershell script that I need to send some parameters to. However, sometimes I do not need to send any or maybe one out of the two.
[CmdletBinding()]
param (
[Parameter(ParameterSetName='SkipAutoLoader')][switch]$SkipAutoLoader,
[Parameter(ParameterSetName='AppPool')][switch]$AppPool
)
[more code here....]
if (-not $SkipAutoLoader) {
$services += "Auto Loader Service"
}
[more code here....]
The above works just fine as long as I have either:
.\Start-AkkServides.ps1 -SkipAutoLoader
or
.\Start-AllServices -AppPool
If I have both together:
.\Start-AllServices -SkipAutoLoader -AppPool
It errors out.
C:\src\Start-AllServices.ps1 : Parameter set cannot be resolved using the specified named parameters.
At line:1 char:1
+ .\Start-AllServices.ps1 -SkipAutoLoader -AppPool
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Start-AllServices.ps1], ParameterBindingException
+ FullyQualifiedErrorId : AmbiguousParameterSet,Start-AllServices.ps1
I also want to be able to determine if the param has the valid -SkipAutoLoader and/or -AppPool but with something else tagged like -SkipAutoLoader43
I would like to say that -SkipAutoLoaderbob is an invalid param. But do not show an error if either param is not present.
Loads Fine:
.\Start-AllServides.ps1 -SkipAutoLoader
Loads Fine:
.\Start-AllServides.ps1 -AppPool
Does Not Load Fine/causes error:
.\Start-AllServides.ps1 -SkipAutoLoader -AppPool
Does Not Load Fine/casues error:
.\Start-AllServides.ps1
Does not say param is not valid:
.\Start-AllServides.ps1 -SkipAutoLoaderbob
Does not say param is not valid:
.\Start-AllServides.ps1 -AppPool7
Possible to do with powershell?
Your parameters are in separate parameter sets (only[1]), so by design they cannot be used together.
If your parameters can be freely combined, you don't need to define parameter sets at all.
Since your script is an advanced one, thanks to [CmdletBinding()] and/or [Parameter()] attributes, calling with non-declared parameter names is automatically prevented.
However, the lack of a default parameter-set designation in the [CmdletBinding()] attribute causes a more fundamental error if you only specify an unsupported parameter name (such as -SkipAutoLoaderbob): PowerShell then doesn't know which of the two defined parameter sets to select, because no declared parameter can be bound (before even considering whether the parameter name given is valid, perhaps surprisingly)
Use [CmdletBinding(DefaultParameterSetName='AppPool')], for instance, to designate the default parameter set.
Assuming that your two parameters can be freely combined and neither is mandatory (which [switch] parameters shouldn't be anyway), your code can be simplified to:
[CmdletBinding()]
param (
[switch] $SkipAutoLoader,
[switch] $AppPool
)
# Output the name of the active parameter set.
$PSCmdlet.ParameterSetName
Note that non-mandatory parameters without explicit parameter-set membership (and other non-default parameter properties) do not require [Parameter()] attributes.
When you invoke the script, you'll see that PowerShell implicitly defines a parameter set in the absence of explicitly declared ones, named __AllParameterSets.
[1] Note that a parameter can belong to multiple explicitly specified parameter sets, via multiple [Parameter(ParameterSetName= '...')] attributes. Any parameter without an explicit parameter-set membership is implicitly part of all parameter sets.

Parameter set cannot be resolved with mutually exclusive non default parameters

Following is full param block signature, I tried almost every possible solution that I'm aware of such as
adding Mandatory to File and Thumbprint parameters sets, removing default parameter set etc, none of which works.
Problem description and desired functionality is this:
Domain parameter is always required while File and ThumbPrint are optional but mutually exclusive.
I run this test as follows:
.\Set-WinRM* -Domain VM-PRO
Parameter set cannot be resolved using the specified named parameters.
function Set-WinRM
{
[CmdletBinding(PositionalBinding = $false, DefaultParameterSetName = "None")]
param (
[Parameter()]
[ValidateSet("HTTP", "HTTPS", "Any")]
[string] $Protocol = "HTTPS",
[Parameter(Mandatory = $true)]
[Alias("ComputerName", "CN")]
[string] $Domain,
[Parameter(ParameterSetName = "File")]
[string] $CertFile,
[Parameter(ParameterSetName = "ThumbPrint")]
[string] $CertThumbPrint,
[Parameter()]
[switch] $SkipTestConnection,
[Parameter()]
[switch] $ShowConfig
)
}
EDIT:
I never use dynamic parameters, if this can't be done normally maybe you can provide an example on how to define them in this example, that would be great.
I copy and pasted your code into Powershell ISE, and added echo $domain to the end to test the parameter. It returns the value normally, without errors:
I don't see any issues with your parameter block, which leads me to believe something else is at fault. If you type out .\Set-WinRM.ps1 -Do, or Set-WinRM -Do can you tab-complete it successfully? If you run Set-WinRM without parameters at all, does it prompt you for Domain:?
I would only expect to see that error if you had additional parameter sets with $domain doing different things, or maybe if a module you have loaded has the Set-WinRM command and it's taking precedence. Try Get-Command Set-WinRM and make sure the CommandType is Function and the Source is blank.

Trying to use parameters dynamically using powershell

I am trying to setup dynamic parameters that vary depending on if you are adding or modifying/removing a drone. Ex: If you are adding a drone you would need its IP/Name/Location.. To remove the drone you would only need its name. I have tried looking online and try various examples I've seen but I am completely stuck here. Any help to steer me in the right direction would be appreciated. I am somewhat new to powershell. Here's what I have.
[CmdletBinding(SupportsShouldProcess=$True)]
Param( [Parameter(Mandatory=$true,
HelpMessage = "Add remove or Modify a drone?")]
[ValidateSet("Add", "Remove", "Modify")]
[String]$Action)
DynamicParam{
if ($action = "Add"){
Param( [Parameter(Mandatory)]
[ValidateSet("NorthAmerica", "SouthAmerica", "NorthernEurope","UK", "CEE", "FRMALU", "SouthernEurope", "AsiaPacific")]
[String]$curRegion,
[Parameter(Mandatory)]
[IPAddress]$ip,
[Parameter(Mandatory)]
[String]$droneName)
}
if ($action = "Remove"){
Param(
[Parameter(Mandatory)]
[string]$droneRemoveName)
}
}
Consider driving your parameter constraints with named Parameter Sets instead. I'm suggesting this because dynamic parameters don't work quite like you think they do, but named parameter sets are an easier way to solve your problem. In case you're interested, here's a blog post explaining how to use dynamic parameters and it winds up being pretty manual parameter handling.
You can add a parameter to more than one parameter set depending on the contexts in which each parameter is required. Instead of using -Action ACTION as a driver for a dynamic parameter, use a [switch] instead, such as -Add and -Remove, and have each switch part of its own parameter set. For example, when defining your parameters, it may look something like this:
Param(
[Parameter(ParameterSetName='Remove')]
[switch]$Remove,
[Parameter(ParameterSetName='Add')]
[switch]$Add,
[Parameter(ParameterSetName='Remove', Mandatory)]
[Parameter(ParameterSetName='Add', Mandatory)]
[string]$IPAddress
)
In this example, -IPAddress is valid when you use the -Add or -Remove switch, but won't be relavant outside of this context. Of course, if a parameter should only be valid for a certain parameter set, don't define it under more than one parameter set name.
If you want to make sure at least one "action" switch is defined before executing, you can check that one of those parameters was used when invoking the cmdlet by checking $PSBoundParameters:
('Add' -in $PSBoundParameters.Keys) -Or ('Remove' -in $PSBoundParameters.Keys)

Parameter, if switch is present, don't permit other parameters

I have a function with parameters like this:
param(
[string[]]$ComputerName,
[string]$exepath,
[string[]]$exeargs,
[switch]$help
)
If the User who uses this function uses the -help switch, there must not be any other parameters declared to call the function. I want to prevent anyone using -help alongside other parameters.
How can I achieve that? I read about_Functions_Advanced_Parameters but it doesn't really help me. I first thought what I need is a ValidateSet but that's different from what I need.
You could use the ParameterSetName attribute:
param(
[Parameter(ParameterSetName='default')]
[string[]]$ComputerName,
[Parameter(ParameterSetName='default')]
[string]$exepath,
[Parameter(ParameterSetName='default')]
[string[]]$exeargs,
[Parameter(ParameterSetName='help')]
[switch]$help
)

Auto Complete User Input PowerShell 2.0

I have a large list of data (over 1000 different values) and I want the user to be able to select certain values from the list from a PowerShell console.
What is the easiest way from within the console to allow the user to quickly select values?
I would like to do something like tab completion or the ability to use the arrow keys to scroll through the values but I am not sure how to do either of these things.
Any advice would be greatly appreciated.
PowerShell tab completion can be extended to custom parameters and parameter values (in v3). However, this is a property of advanced functions. You can use the ValidateSetAttribute to do that.
Check the Technet help topic on advanced functions: http://technet.microsoft.com/en-us/library/hh847806.aspx
You can replace the tabexpansion (v2) and tabexpansion2 (v3) function in PowerShell to auto complete parameter values outside of advanced functions. You can get a basic definition of this in PowerShell v3 by running
Get-Content function:TabExpansion2
Here is an example of showing custom tab expansion function.
http://www.powershellmagazine.com/2012/11/29/using-custom-argument-completers-in-powershell-3-0/
But, if you want to the user to be able to auto complete values for a Read-Host kind of input, you need to write a proxy for Read-Host to achieve that.
You can, optionally, look at PowerTab module at http://powertab.codeplex.com/
For folks who are looking for a way to do this and are fortunate enough to be using PS v3 (and my apologies for all those required to stay with V2):
The easiest way to achieve this is using the "ValidateSet" option in your input parameters.
function Show-Hello {
param (
[ValidateSet("World", "Galaxy", "Universe")]
[String]$noun
)
$greetingString = "Hello, " + $noun + "!"
Write-Host "`t=>`t" $greetingString "`t<="
}
ValidateSet throws an error if a user attempts to use any other input:
Show-Hello "Solar System"
Show-Hello : Cannot validate argument on parameter 'noun'. The argument `
"Solar System" does not belong to the set "World,Galaxy,Universe" specified `
by the ValidateSet attribute. Supply an argument that is in the set and `
then try the command again.
It also adds tab-completion to your function for that parameter. And if it is the FIRST parameter for your function, you don't even have to type in "-noun" for the tab-complete to make suggestions for its value.