131

I have a script to which I pass server name(s) in $args.

This way I can do stuff to this (these) server(s) using foreach:

.\script.ps1 host1 host2 host3

foreach ($i in $args)
{
    Do-Stuff $i
}

I'd like to add a named optional parameter called vlan. I've tried:

Param(
    [string]$vlan
)

foreach ($i in $args)
{
    Write-Host $i
}
Write-Host $vlan

It works if you pass a -vlan parameter but if you don't then the script auto assigns the last server name to $vlan.

So, how can you pass single or multiple parameters plus an optional named parameter to a PowerShell script?

Ideally, here are valid examples:

.\script.ps1 host1
.\script.ps1 host1 host2 host3
.\script.ps1 host1 host2 -vlan office

5 Answers 5

237

The easiest way is probably to use two parameters: One for hosts (can be an array), and one for vlan.

param([String[]] $Hosts, [String] $VLAN)

Instead of

foreach ($i in $args)

you can use

foreach ($hostName in $Hosts)

If there is only one host, the foreach loop will iterate only once. To pass multiple hosts to the script, pass it as an array:

myScript.ps1 -Hosts host1,host2,host3 -VLAN 2

...or something similar.

Sign up to request clarification or add additional context in comments.

3 Comments

thanks for including the info on how to call the script - I'm often missing little pieces like that in powershell.
If you are executing outside a powershell (in wsl for example), then you need to use the -Command flag and to quote the variable. pwsh -Command myScript.ps1 -Hosts "host1,host2,host3" -VLAN 2
@miah Nice one. I'd adjust your command a little bit like pwsh -Command .\myScript.ps1 -Hosts "host1,host2,host3" -VLAN 2
39

One way to do it would be like this:

 param(
       [Parameter(Position=0)][String]$Vlan,
       [Parameter(ValueFromRemainingArguments=$true)][String[]]$Hosts
    ) ...

This would allow multiple hosts to be entered with spaces.

6 Comments

Really nice! Except your example is missing a ']' to close the second Parameter attribute.
This one should be the best answer.
This is the way.
I don't see how this allows vlan to be optional.
@Tony all parameters are optional by default. You can add the line [Parameter(Mandatory=$false)] before [string]$vlan if you want for readability. But it won't change functionality.
|
31

Parameters take input before arguments. What you should do instead is add a parameter that accepts an array, and make it the first position parameter. ex:

param(
    [Parameter(Position = 0)]
    [string[]]$Hosts,
    [string]$VLAN
    )

foreach ($i in $Hosts)  
{ 
    Do-Stuff $i
}

Then call it like:

.\script.ps1 host1, host2, host3 -VLAN 2

Notice the comma between the values. This collects them in an array

Comments

1

I was having issues doing this in my yml file and then I found this link and adding "-Command" to the front of my script solved it:

https://michlstechblog.info/blog/powershell-passing-an-array-to-a-script-at-command-line/

Comments

-8

I call a scheduled script who must connect to a list of Server this way:

Powershell.exe -File "YourScriptPath" "Par1,Par2,Par3"

Then inside the script:

param($list_of_servers)
...
Connect-Viserver $list_of_servers.split(",")

The split operator returns an array of string

2 Comments

This is a horrible way to do it. You should be making $list_of_servers an array: [string[]]$list_of_servers
Thank you, never realized it was so scary. That works from many years.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.