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

本小妞迷上赌 提交于 2019-12-22 09:25:29

问题


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.


回答1:


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


来源:https://stackoverflow.com/questions/30737491/how-do-i-define-functions-within-a-cmdletbinding-script

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!