简体   繁体   中英

Powershell functions, parameters and arg

I write own powershell func for debug like:

function StartDebug {
    param (
        [PARAMETER(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        $FunctionName,
        [PARAMETER(Mandatory = $false)]
        $OtherArg
    )

    try {& $FunctionName $OtherArg} catch {...} finally {...}

and use it everyway, but i need more arg after $FunctionName. is it realistic to pass many arguments in this case bec use from 0 to 10 arg. do I have to list all the arguments that can be in the parameters of the function? like:

function StartDebug {
    param (
        [PARAMETER(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        $FunctionName,
        [PARAMETER(Mandatory = $false)]
        $OtherArg,
        [PARAMETER(Mandatory = $false)]
        $OtherArg1,
        [PARAMETER(Mandatory = $false)]
        $OtherArg2,
        [PARAMETER(Mandatory = $false)]
        $OtherArg3
    )

    try {& $FunctionName $OtherArg OtherArg1 OtherArg2 OtherArg3 } catch {...} finally {...}

but i dont use positional parameters in code and too many named parameters in code (~100)

Interested in any ideas about this. tnx!

The magic word is Splatting . You can provide an array or a hashtable containing your arguments to a function. The splatter is written with an @VariableName instead of the $ :

function StartDebug {
    param (
        [PARAMETER(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        $FunctionName,
        [PARAMETER(Mandatory = $false)]
        $OtherArg
    )

    try {& $FunctionName @OtherArg    # Watch out for the @ in the OtherArg
    } catch {$_} finally {}
}


$FunctionName = 'Get-ChildItem'

$Splatter = @{
    Path      = 'C:\'
    Filter    = 'Users'
    Directory = $true
}

$Splatter2 = @('c:\')

StartDebug $FunctionName $Splatter

StartDebug $FunctionName $Splatter2

However if you want to use single items as $OtherArg you will have to provide them as single element array as can be seen with $Splatter2 . Or extend your function to transform single arguments in arrays automatically, but thats up to you.

I think you better run it using scriptblock:

$result = Invoke-DeepDebug { Get-ChildItem -Path 'C:\' ; Get-Service -InformationAction Continue}

And in Invoke-DeepDebug you can work with $Command.AST as deep and detailed as you want.

Function Invoke-DeepDebug {
    param(
        [Parameter(Mandatory=$true, Position=0)]
        [Scriptblock]$Command
    )

    Write-Host -f Cyan "Executing " -n
    Write-Host -f Magenta $Command.Ast.Extent.Text -n 
    Write-Host -f Yellow " ... " -n

    $result = $null
    try { 
        $result = Invoke-Command $Command -ErrorAction Stop
        Write-Host -f Green "OK!" 
    } catch { 
        Write-Host -f Red "Error"
        Write-Host -f Red "`t$($_.Exception.Message)"
    }
    return $result
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM