whoami
whoami

Reputation: 1899

Correct parameters values not passed on to the function

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

Answers (2)

mklement0
mklement0

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:

    • The [CmdletBinding()] attribute, which makes a function or script an advanced one, with behaviors on par with (compiled) PowerShell cmdlets - see about_Functions_Advanced

In 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.


When to choose which syntax form:

  • 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

marsze
marsze

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

Related Questions