开发者

Powershell - Dynamic Function Call

With custom Powershell functions all function output is returned. I'm attempting to remove that limitation/confusion by writing a wrapper function that will return just $true or $false.

However, I'm struggling with the dynamic function call . . . specifically passing the arguments.

Note that both the function name and the function arguments are passed to "ExecBoolean".

Code Sample:

# Simplifies calls to boolean functions in Powershells scripts
# Helps solve this problem -> http://www.vistax64.com/powershell/107328-how-does-return-work-powershell-functions.html

function Foo([string]$sTest, [int] $iTest)
{
    Write-Host "sTest [" $sTest "]."
    Write-Host "iTest [" $iTest "]."
    if ($iTest -eq 1)
    {
        return $true
    }
    else
    {
        return $false
    }
}

function ExecBoolean ([string] $sFunctionName, [array] $oArgs)
{   
    Write-Host "Array Length = " $oArgs.Length ", Items = [" $oArgs[0..($oArgs.Length - 1)] "]"

    $oResult = & $sFunctionName $oArgs[0..($oArgs.Length - 1)]

    # Powershell returns all function output in oResult, just get the last item in the array, if necessary.                     
    if ($oResult.Length -gt 0) 
    {
        return $oResult[$oResult.Length - 1]
    } 
    else 
    {
        return $oResult
    }
}

$oResult = ExecBoolean "Foo" "String1", 1

Write-Host "Result = " $oResult

Current Output:

Array Length =  2 , Items = [ String1 1 ] 
sTest [ String1 1 ]. 
iTest [ 0 ]. 
Result =  False

Desired Output:

开发者_开发百科
Array Length =  2 , Items = [ String1 1 ]
sTest [ String1 ].
iTest [ 1 ].
Result =  True

Is this possible in Powershell v1.0?

Thanks.


I would use Invoke-Expression like this:

function ExecBoolean ([string] $sFunctionName)
{   
    Write-Host "Array Length = " $args.Length ", Items = [" $args[0..($args.Length - 1)] "]"
    $oResult = Invoke-Expression "$sFunctionName  $($args -join ' ')"
    # Powershell returns all function output in oResult, just get the last item in the array, if necessary.                     
    if ($oResult.Length -gt 0) 
    {
        return $oResult[$oResult.Length - 1]
    } 
    else 
    {
        return $oResult
    }
}
ExecBoolean Foo String1 1

Note that:

  1. I use $args which is imho more comfortable, because you don't to pass the arguments as a array. However, you could use your $oArgs as well with no problem (the only line that matters is the one with Invoke-Expression).
  2. This will work only for simple types (strings, ints, ...), but not for e.g. FileInfo, because the objects are converted to strings in $($args -join ' ').
  3. There is one more option, but it is too verbose: ExecBoolean Foo @{sTest="String1"; iTest=1}. So you would pass parameters in a hashtable. You would need to alter Foo to accept hashtable of course. In this case you could pass any type in, because you could call Foo using & operator.
  4. See below

I would not recommend this approach, because of the limitations (but it can happen that maybe others will come up with better solution).
If you just want to ensure that no output is returned from Foo, you might create a script that parses other scripts that call Foo and checks that every call to "Foo" must be prepended with $null =.

If you switch to PowerShell V2, there is better way called splatting. For more info look at How and Why to Use Splatting (passing [switch] parameters)


$oResult = & $sFunctionName $oArgs[0..($oArgs.Length - 1)]

Here you're passing the function only one argument —an array— so the second parameter in Foo defaults to 0.

If you just want to discard output from a statement/expression, there are ways to do so, like piping it to Out-Null or "casting" to void.


Personally, I would just use:

functionName -as [bool]

This will coerce the results of the function into a boolean.

It's much more readable later on.

Hope this helps

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜