1

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!

JustDj
  • 23
  • 4

2 Answers2

0

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.

T-Me
  • 1,814
  • 1
  • 9
  • 22
  • Wow. It working. Сan you describe the process "transform single arguments in arrays" in more detail? – JustDj May 19 '21 at 11:50
  • technically you have 2 options. 1. check `if` the `.count` of `$OtherArg` is high than 1 , then use `@` `else` use `$`. 2. if the `if` the `.count` is 1 place `$OtherArg` in `@()` like in `$Splatter2` or write `[array]$OtherArg` in both cases it will be cast to an array. – T-Me May 20 '21 at 06:21
0

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
}
filimonic
  • 3,988
  • 2
  • 19
  • 26