https://www.techtarget.com/searchwindowsserver/tutorial/Try-default-values-in-PowerShell-parameters-for-flexibility
When you learn to write PowerShell functions, you might start by solving a specific problem. But as your projects grow more complex, adding flexibility to your scripts will help in the future.
As you use PowerShell functions more and gain more scripting experience, you'll see ways the function would be more useful if it had the versatility to solve the same problem but in a slightly differently way. Learning how to use default values in parameters makes your code both able to adapt to different situations and simpler to understand. This article will explain how to set default values to make your scripts smarter while showing you how to avoid common pitfalls that can introduce issues or unnecessary complexity.
A parameter default value is the value given to a parameter if an explicit value isn’t specified. For example, if you run Get-ChildItem without any parameters, it defaults to using your current working directory as if you had executed Get-ChildItem -Path .\.
Another example is using the Copy-Item cmdlet to copy a file. If you don't specify a value to the Destination parameter, then PowerShell automatically copies the item to the current working directory. These two commands produce the same result of copying the file to the same directory where the command is executed:
Copy-Item -Path C:\path\file.txt
Copy-Item -Path C:\path\file.txt -Destination .\
As a PowerShell user, you have the power to define default parameters for both functions that you write and functions that you consume.
PowerShell lets users define default values for parameters in two ways:
In the param block of a function, any parameter can declare a default value by using the assignment operator, which is the equal sign, and specifying a value. For example:
Function Test-DefaultValues {
[CmdletBinding()]
param (
[string]$String = "Default String"
)
Write-Host $String
}
The code gives the $String parameter a default value of "Default String." Running this function without parameters will generate the output that text.
You can also use the subexpression operator $() to execute PowerShell code to assign a default value. In the following example, the function calculates how many days there are until Friday:
Function Test-DefaultValues {
[CmdletBinding()]
param (
[int]$DaysUntilFriday = $(switch ($([DateTime]::Now.DayOfWeek)) {
'Monday' { 4 }
'Tuesday' { 3 }
'Wednesday' { 2 }
'Thursday' { 1 }
'Friday' { 0 }
'Saturday' { 6 }
'Sunday' { 5 }
})
)
Write-Host "There are $DaysUntilFriday days until Friday."
}
If you run this function with no parameters and enter Test-DefaultValues on the command line on a Monday, then the output will show: There are 4 days until Friday.
Default parameter values can also be defined not only by the author of the function but also by the user. PowerShell has a built-in variable called $PSDefaultParameterValues that lets users specify default values for parameters across cmdlets, functions and scripts.
The $PSDefaultParameterValues variable is a hashtable with extra validation. The key must follow the CommandName:ParameterName format. The value assigned to the key will be the default value for that parameter. For example, if you use the Test-DefaultValues function with a new parameter, then you can set the default value for that function with the same syntax used to edit hashtables:
$PSDefaultParameterValues['Test-DefaultValues:WriteWelcomeMessage'] = $false
To test the function to see how PowerShell handles default values, set a default value for a switch parameter:
Function Test-DefaultValues {
[CmdletBinding()]
param (
[switch]$WriteWelcomeMessage = $true
)
if ($WriteWelcomeMessage) {
Write-Host "Welcome!"
} else {
Write-Host "No welcome message."
}
}
When executed without setting the $PSDefaultParameterValues variable, the output is Welcome!
If you set the $PSDefaultParameterValues variable, the output is No welcome message.
This shows user-defined default values via the $PSDefaultParameterValues variable have higher priority over defaults defined in the function.
You can define parameter values more broadly using the asterisk wildcard in $PSDefaultParameterValues to apply default values to multiple commands that match a pattern. For example, to automatically pass the Verbose switch to all cmdlets that start with Get-, use the following:
$PSDefaultParameterValues['Get-*:Verbose'] = $true
The result ensures any Get- command will run in verbose mode by default.
It's also possible to scope parameters to specific modules, assuming the module uses a standard naming convention. For example, to specify a set of properties to all Get-Mg* commands in the Microsoft.Graph module, you can use:
$PSDefaultParameterValues['Get-Mg*:Properties'] = @(
'displayName',
'id',
'userPrincipalName',
'mail',
'accountEnabled'
)
When writing an advanced function in PowerShell, parameters are optional by default. You can make a parameter mandatory by adding the Mandatory attribute. PowerShell will prompt the user if a mandatory parameter isn't provided.
When using parameter sets, parameters can be conditional. It's important to understand how default values operate with the optional, mandatory and conditional types.
In the previous examples, all the parameters in the Test-DefaultValues function were optional because they had no Mandatory attribute. Even though the parameters were essential to the function's operation, default values allowed the function to run without user input. This is similar to how the Path parameter in Get-ChildItem or the Destination parameter in Copy-Item works.
If you mark a parameter as Mandatory, then you can't specify a default value. For example, if you test this function, then you'll still get a prompt to supply a value for $String even though it has a default value because the Mandatory attribute overrides default value behavior:
Function Test-DefaultValues {
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[string]$String = "Default String"
)
Write-Host $String
}
If you develop the function in Visual Studio Code with the PowerShell extension, then the PSScriptAnalyzer will underline $String as a warning because assigning a default value to a Mandatary parameter goes against best practices
Default values work the same way within parameter sets as they do outside of them. If an optional parameter inside of the parameter set has a default value, then that value will be used when the function is called.
If a Mandatory parameter inside of the parameter set has a default value, then PowerShell will ignore it and prompt the user for input. This can cause confusion, especially when PowerShell tries to infer which parameter set to use.
Consider the following example:
Function Test-DefaultValues {
[CmdletBinding()]
param (
[Parameter(
ParameterSetName = "Default"
)]
[string]$String,
[Parameter(
ParameterSetName = "Custom"
)]
[string]$CustomString = "Custom String Value"
)
if ($PSCmdlet.ParameterSetName -eq "Default") {
$String = "Default String Value"
}
else {
$String = $CustomString
}
Write-Host $String
}
It might appear PowerShell would choose the Custom parameter set because $CustomString has a default value, but PowerShell will output an error message. PowerShell can't determine which parameter set to use when no arguments are passed and a Mandatory parameter exists without a clear default set
To resolve this, declare a default parameter set inside the CmdletBinding block:
Function Test-DefaultValues {
[CmdletBinding(
DefaultParameterSetName = "Custom"
)]
With that change, PowerShell will default to the Custom parameter set.
To use PowerShell to generate passwords, then you can write a simple function to make a moderately complex 12-character password:
Function New-Password {
[char[]]$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()'
(1..12 | ForEach-Object {
$chars | Get-Random -Count 1
}) -join ''
}
Running the function will produce a reasonably secure password, such as 6Qh%2MVDkUP6.
However, this is a single-purpose function with no flexibility. To improve it, add a Length parameter with a sensible default value:
Function New-Password {
param (
[int]$Length = 12
)
[char[]]$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()'
(1..$Length | ForEach-Object {
$chars | Get-Random -Count 1
}) -join ''
}
Now, you can customize the password length without compromising the sensible default value:
New-Password -Length 30
This command will output a password, such as apIA!vcp0d0sQ%gIl5IrMhM2S1YG1).
To make the password generation function more versatile, you can add support for additional scenarios, such as making a simple password:
Function New-Password {
[CmdletBinding()]
param (
[int]$Length = 12,
[switch]$Simple
)
[char[]]$simpleChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
[char[]]$complexChars = '!@#$%^&*()'
$chars = if ($Simple) {
$simpleChars
} else {
$simpleChars + $complexChars
}
(1..$Length | ForEach-Object {
$chars | Get-Random -Count 1
}) -join ''
}
Then run the command:
New-Password -Length 20 -Simple
This will output a simple password of 20 characters, such as zsB1AmdOmTwk0LT3ysgx.
Add a parameter set to let the user input a custom set of characters:
Function New-Password {
[CmdletBinding(
DefaultParameterSetName = 'default'
)]
param (
[Parameter(
ParameterSetName = 'default'
)]
[Parameter(
ParameterSetName = 'customChars'
)]
[int]$Length = 12,
[Parameter(
ParameterSetName = 'default'
)]
[switch]$Simple,
[Parameter(
Mandatory,
ParameterSetName = 'customChars'
)]
[char[]]$CustomChars
)
[char[]]$simpleChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
[char[]]$complexChars = '!@#$%^&*()'
$chars = if ($PSCmdlet.ParameterSetName -eq 'customChars') {
$CustomChars
} elseif ($Simple) {
$simpleChars
} else {
$simpleChars + $complexChars
}
(1..$Length | ForEach-Object {
$chars | Get-Random -Count 1
}) -join ''
}
Run the command:
New-Password -Length 25 -CustomChars 'abc123!@#'
PowerShell will output a 25-character password using only the specified characters, such as bc1ca3@cc323acb2b22bc!ac3.
All these additions don't take away from our original goal to run New-Password without parameters to generate a reasonably secure, 12-character password.
Another practical PowerShell technique is to write a function that works on local and remote computers. To capture the machine name, write a function that uses a ComputerName parameter and assign it a default value that corresponds to the local machine.
In this example, the function searches through the event logs of the local machine and returns all events that are failed login attempts (event ID 4648).
Function Get-ExplicitLogins {
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
Id = 4648
}
}
To make the function more useful, add a ComputerName parameter and set its default value to the local computer name.
Function Get-ExplicitLogins {
param (
[string]$ComputerName = $env:COMPUTERNAME
)
Get-WinEvent -ComputerName $ComputerName -FilterHashtable @{
LogName = 'Security'
Id = 4648
}
}
You can call the Get-ExplicitLogins function without any parameters and to query the local computer.
To specify a remote computer, pass the function to a computer name:
Get-ExplicitLogins -ComputerName 'Test-PC01'
"Smart defaults" is a common concept in software development that refers to building functions that are useful even when no parameters are given. It's helpful to consider them when writing PowerShell functions that might be used by other people, especially someone who is less familiar with PowerShell.
An excellent example of this concept is the Out-File cmdlet. This cmdlet lets you save output to a file. One of its parameters is Encoding, which controls text formatting in the file. If PowerShell required the user to always specify the encoding, that would be a frustrating experience. Instead, PowerShell uses default encoding automatically when one isn't specified.
As with all scripting in PowerShell, it's possible to make mistakes while using default values. Here are some common pitfalls and how to avoid them:
Anthony Howell is an IT strategist with extensive experience in infrastructure and automation technologies. His expertise includes PowerShell, DevOps, cloud computing, and working in both Windows and Linux environments.
09 Oct 2025