Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I define functions within a CmdletBinding() script?

I'm writing a script that I'd like to use PowerShell's CmdletBinding() with. Is there a way to define functions in the script? When I try, PowerShell complains about "Unexpected toke 'function' in expression or statement"

Here's a simplified example of what I'm trying to do.

[CmdletBinding()]
param(
    [String]
    $Value
)

BEGIN {
    f("Begin")
}

PROCESS {
    f("Process:" + $Value)
}

END {
    f("End")
}

Function f() {
    param([String]$m)
    Write-Host $m
}

In my case, writing a module is wasted overhead. The functions only need to be available to this one script. I don't want to have to mess with the module path or the script location. I just want to run a script with functions defined in it.

like image 778
mojo Avatar asked Jun 09 '15 16:06

mojo


People also ask

How do you define a function in PowerShell script?

A function in PowerShell is declared with the function keyword followed by the function name and then an open and closing curly brace. The code that the function will execute is contained within those curly braces.

How do you create a function in PowerShell?

To define a function, you use the function keyword, followed by a descriptive, user-defined name, followed by a set of curly braces. Inside the curly braces is a scriptblock that you want PowerShell to execute. Below you can see a basic function and executing that function.

How do I use CmdletBinding?

To use the CmdletBinding attribute, you need to define a function and place the attribute before the param block. You can optionally define parameters with the Parameter attribute to adjust how parameters behave.

How do you call a PowerShell function?

To perform or "invoke" a method of an object, type a dot (.), the method name, and a set of parentheses "()". If the method has arguments, place the argument values inside the parentheses. The parentheses are required for every method call, even when there are no arguments.


1 Answers

You use begin, process, and end blocks when your code is supposed to process pipeline input. The begin block is for pre-processing and runs a single time before processing of the input starts. The end block is for post-processing and runs a single time after processing of the input is completed. If you want to call a function anywhere other than the end block you define it in the begin block (re-defining it over and over again in the process block would be a waste of resources, even if you didn't use it in the begin block).

[CmdletBinding()]
param(
    [String]$Value
)

BEGIN {
    Function f() {
        param([String]$m)
        Write-Host $m
    }

    f("Begin")
}

PROCESS {
    f("Process:" + $Value)
}

END {
    f("End")
}

Quoting from about_Functions:

Piping Objects to Functions

Any function can take input from the pipeline. You can control how a function processes input from the pipeline using Begin, Process, and End keywords. The following sample syntax shows the three keywords:

function <name> { 
    begin {<statement list>}
    process {<statement list>}
    end {<statement list>}
}

The Begin statement list runs one time only, at the beginning of the function.

The Process statement list runs one time for each object in the pipeline. While the Process block is running, each pipeline object is assigned to the $_ automatic variable, one pipeline object at a time.

After the function receives all the objects in the pipeline, the End statement list runs one time. If no Begin, Process, or End keywords are used, all the statements are treated like an End statement list.


If your code doesn't process pipeline input you can drop begin, process, and end blocks entirely and put everything in the script body:

[CmdletBinding()]
param(
    [String]$Value
)

Function f() {
    param([String]$m)
    Write-Host $m
}

f("Begin")
f("Process:" + $Value)
f("End")

Edit: If you want to put the definition of f at the end of your script you need to define the rest of your code as a worker/main/whatever function and call that function at the end of your script, e.g.:

[CmdletBinding()]
param(
    [String]$Value
)

function Main {
    [CmdletBinding()]
    param(
        [String]$Param
    )

    BEGIN   { f("Begin") }
    PROCESS { f("Process:" + $Param) }
    END     { f("End") }
}

Function f() {
    param([String]$m)
    Write-Host $m
}

Main $Value
like image 123
Ansgar Wiechers Avatar answered Oct 13 '22 00:10

Ansgar Wiechers