Home > Software engineering >  passing $MyInvocation.UnBoundArguments to a nested function in Powershell
passing $MyInvocation.UnBoundArguments to a nested function in Powershell

Time:10-28

I want a function to pass all of it arguments to another function. Is there a better way of doing this? My version doesn't seem to work right however.

function remote {
    $fargs = $MyInvocation.UnboundArguments

    remote_version1 @fargs      
}

function remote_version1 {
param(
    [alias("m", "computer")]    
    [Parameter(Mandatory=$false)]   [string]$Machine  = "",
    [Parameter(Mandatory=$false)]   [string]$loc_file = "",
    [Parameter(Mandatory=$false)]   [string]$rem_file = "",
    [Parameter(Mandatory=$false)]   [switch]$tmp,
    [Parameter(Mandatory=$false)]   [switch]$banner,
    [Parameter(Mandatory=$false)]   [int]$profile     = $script:remote_profile,  
    [Parameter(Mandatory=$false)]   [int]$Hop         = $script:remote_hop        # Second Hop Mode     
)
    #write-host $MyInvocation.BoundParameters   
    write-host "loc_file: $loc_file"
    write-host "rem_file: ($rem_file)"
}

$common_flags              = @{}
$common_flags["Banner"]    = $true
$common_flags["Machine"]   = "mymachine"
$common_flags["Hop"]       = $true
$common_flags["Profile"]   = $true
remote @common_flag -loc_file .\file.txt  -tmp

Result:

loc_file: .\file.txt
rem_file: True   ##<==== Why True?  SHould be "" since 
                 ##      it isn't set when called?? 

(I can't seem to reproduce the output by snipping the code out of script.. makes me think powershell has some type of pointer bug? But this is the problem i'm having... $rem_file is set to a boolean for some reason, when its a string...)

Maybe i'm passing the wrong type into the "splat operator" @, and the orderingof items is random in the hash? but powershell doesn't seem to complain its the wrong object type?

Is there a way to convert a string into a company and execute it instead of using splat?

CodePudding user response:

The automatic $args variable has built-in magic when used for splatting (@args), allowing it to pass named arguments through properly - note that this does not work with any other arrays, whether self-created array or returned from $MyInvocation.UnboundArguments.

Therefore, the following should meet your needs:

function remote {
  # @args passes both named and positional (unnamed) arguments through.
  remote_version1 @args      
}

Note:

  • If the relaying function (remote) itself had declared parameters (with a param(...) block), you could also relay them with @PSBoundParameters, via automatic $PSBoundParameters variable.

  • If a relaying function with declared parameters is non-advanced, you may use @PSBoundParameters in addition to passing unbound arguments through with @args, whereas advanced functions by definition prevent passing unbound arguments (in other words: they do not support $args).

CodePudding user response:

UnboundArguments is an Array instead of a Hash. I simply print the Array to convert it to a string and feed it to invoke-expression.

        $fargs = $MyInvocation.UnboundArguments
        $fargs = $fargs -replace "True", "`$true"
        $fargs = $fargs -replace "False", "`$false"
        invoke-expression  "remote_version1 $fargs"
  • Related