Reputation: 1899
I have a file called TestFunc.ps1. Its contents are as follows
Function TestFunc([string]$param1, [string]$param2)
{
Write-Host "------------------"
Write-Host $param1
Write-Host $param2
Write-Host "------------------"
}
TestFunc $param1 $param2
I called it as follows
C:\Test\TestFunc.ps1 "Hello" "World"
The output is as follows
------------------
------------------
I expect the output as
------------------
Hello
World
------------------
What am I doing wrong here?
Upvotes: 2
Views: 1083
Reputation: 437082
To complement marsze's helpful and effective answer:
PowerShell has two largely equivalent syntax forms for defining parameters - leaving PSv5+ class
definitions aside[1]:
Note: For brevity, the parameter lists are placed on a single line below; however, both syntax forms allow placing individual parameters on their own line.
For functions only:
C/C#-like: a ,
-separated list of parameter-variable declarations inside (...)
after the function name and before the opening {
; e.g.:
function foo ($bar, $baz) {
# ...
}
For scripts and functions too, as well as script blocks ({ ... }
, which are like anonymous functions):
PowerShell-specific: A ,
-separated list of parameter-variable declarations inside param(...)
, which must be the first statement inside the body (apart from comments and using
directives):
# --- Script foo.ps1
param($bar, $baz)
# ...
# --- Function
# This example is fully equivalent to `foo ($bar, $baz) { ...` above.
# Note that no () is needed after the function name.
function foo {
param($bar, $baz)
# ...
}
# --- Script block
& {
param($bar, $baz)
# ...
} # arguments...
For brevity, the following optional elements were omitted above:
On individual parameter declarations:
Typing; e.g., to declare parameter $foo
as type [int]
(System.Int32
):
[int] $foo
Parameter attributes, typically, but not exclusively via the [Parameter()]
attribute; among other things, the latter determines whether the associated parameter is mandatory; e.g.:
[Parameter(Mandatory=$true)] [int] $foo
Above the param(...)
statement only:
[CmdletBinding()]
attribute, which makes a function or script an advanced one, with behaviors on par with (compiled) PowerShell cmdlets - see about_Functions_AdvancedIn simple (non-advanced) scripts and functions it is also an option not to declare any parameters at all, in which any arguments passed are contained in the automatic $args
variable, which is a regular PowerShell array ([object[]]
).
You can even combine $args
with declared parameters: $args
then contains only those arguments that didn't bind to declared ones.
By contrast, in advanced scripts and functions, you are fundamentally only permitted to pass arguments that bind to declared parameters.
Script files and script blocks must use a param(...)
statement - the C#-like syntax isn't available.
Functions can technically use the C#-like syntax and the param(...)
interchangeably, except if the [CmdletBinding()]
attribute is needed, in which case only the param(...)
syntax works.
That said, for consistency and easier extensibility (making a function an advanced one later), the param(...)
syntax is generally preferable.
Also, using the C#-like syntax frequently can more easily lead to syntax confusion when invoking a function, given that PowerShell cmdlets and functions are invoked like shell commands (no parentheses, whitespace-separated arguments), not like C# methods; e.g., foo 1 2
(or foo -bar 1 -baz 2
) rather than foo(1, 2)
[1] The method declarations in class
definitions must use C#-like syntax, and no parameter attributes are supported (they're only supported on properties). Just like methods on native .NET types, class methods must also be called with method syntax - see this answer and help topic about_Classes.
Upvotes: 1
Reputation: 17035
The parameters are defined for the scope of the function, and not the script.
What you want is a Param section:
param ([string]$param1, [string]$param2)
function TestFunc([string]$param1, [string]$param2) {
Write-Host "------------------"
Write-Host $param1
Write-Host $param2
Write-Host "------------------"
}
TestFunc $param1 $param2
Of course, having duplicate variable names is misleading, but I it's just a test function. In your case, you wouldn't even need a function at all:
param ([string]$param1, [string]$param2)
Write-Host "------------------"
Write-Host $param1
Write-Host $param2
Write-Host "------------------"
Or alternatively:
param ([string]$param1, [string]$param2)
function TestFunc {
Write-Host "------------------"
Write-Host $param1
Write-Host $param2
Write-Host "------------------"
}
TestFunc
Or use the $args
automatic variable, without defining any parameters at all:
function TestFunc {
Write-Host "------------------"
Write-Host $args[0]
Write-Host $args[1]
Write-Host "------------------"
}
TestFunc foo bar
Upvotes: 5