简体   繁体   English

如何从变量调用Powershell函数

[英]How to call a powershell function from a variable

I want to create a function to call a function with parameters and output the results of the called function. 我想创建一个函数来使用参数调用函数并输出被调用函数的结果。

Working Code: 工作代码:

$MockDataPath = 'C:\temp'
$MockDataFunctionName = 'Get-SomeFunction'
$Results = Get-SomeFunction -Parameter1 'SomeParameter'
$Results | Export-CliXML "$MockDataPath\$MockDataFunctionName.xml"

What I want to do: The first $Results = line is where I'm having the issue. 我想做什么:第一个$Results =行是我遇到问题的地方。 I know it does not work but I have been unable to find a solution online. 我知道它不起作用,但是我一直无法在线找到解决方案。 I'm also unsure if the $MockFunctionParameters is the correct approach for parameter passing. 我也不确定$MockFunctionParameters是否是传递参数的正确方法。

Function Get-MockedData {
  [CmdletBinding()]
  param(
    [Parameter(
      Position = 0,
      Mandatory = $true,
      ValueFromPipelineByPropertyName = $true,
      HelpMessage = "Enter the name of the function you want to get mock data from.  Ex: Get-GenericCredential")]
    [ValidateNotNullOrEmpty()]
    [string]
    $MockFunctionName,

    [Parameter(
      Mandatory = $false,
      ValueFromPipelineByPropertyName = $true,
      HelpMessage = "Enter the parameters of the function you want to get mock data from.  Ex: '-Parameter1 SomeParameter'")]
    [ValidateNotNullOrEmpty()]
    [string]
    $MockFunctionParameters,

    [Parameter(
      Mandatory = $false,
      ValueFromPipelineByPropertyName = $true,
      HelpMessage = "Enter the directory you want the mocked data to appear.  Default: 'C:\temp'")]
    [ValidateNotNullOrEmpty()]
    [string]
    $MockDataOutputPath = 'C:\temp'
  )

  $Results = $MockFunctionName $MockFunctionParameters
  $Results | Export-Clixml "$MockDataOutputPath\$MockDataFunctionName.xml"
}

You're going to need to use Splatting rather than passing the parameters as a string. 您将需要使用Splatting而不是将参数作为字符串传递。 So you'd call it as Get-MockedData -MockFunctionName <name> -MockFunctionParameters @{Parameter1 = "SomeParameter} 因此,您可以将其称为Get-MockedData -MockFunctionName <name> -MockFunctionParameters @{Parameter1 = "SomeParameter}

Then you call the function in $Result using & . 然后,使用&调用$Result的函数。

$Results = &$MockFunctionName @MockFunctionParameters

Bruce Payette pointed out that Invoke-Expression is considered harmful (and in this case could result in injection because you're passing arbitrary parameters and functions). Bruce Payette指出, Invoke-Expression被认为是有害的(在这种情况下,可能会导致注入,因为您传递了任意参数和函数)。


Alternately, you can use DynamicParameters and actually have it include the parameters from the original function (Which will still work with splatting as above but also allows clearer functionality when using interactively). 或者,您可以使用DynamicParameters,并实际上使它包含原始函数的参数(这仍然可以像上面那样使用Splatting,但在交互使用时也可以提供更清晰的功能)。

It doesn't have full functionality but does offer tab completion for parameters (it has a few issues there such as get-content not showing -path but completing -pa<tab> into -path ) although it will not always offer tab completion with ValidationSet (It works on a custom function but failed on New-Item -itemtype so it might be an issue with built-in commands). 它没有完整的功能,但确实提供了参数的制表符补全功能(尽管有一些问题,例如get-content不显示-path但将-pa<tab> -path-path ),尽管它并不总是提供以下功能: ValidationSet (它在自定义函数上有效,但在New-Item -itemtype上失败,因此内置命令可能会出现此问题)。 It does not need -MockFunctionParameters since those parameters can be splatted ( $splat = @{path = "test.xml"} ) directly in to the function call Get-MockedData get-content @splat . 它不需要-MockFunctionParameters因为可以直接将这些参数( $splat = @{path = "test.xml"}Get-MockedData get-content @splat到函数调用Get-MockedData get-content @splat

function Get-MockedData {
    [cmdletbinding()]
    param(
        [Parameter(
            Position = 0,
            Mandatory = $true,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage = "Enter the name of the function you want to get mock data from.  Ex: Get-GenericCredential")]
        [ValidateNotNullOrEmpty()]
        [ValidateScript( {Get-Command $_})]
        [string]
        $MockFunctionName,

        [Parameter(
            Mandatory = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage = "Enter the directory you want the mocked data to appear.  Default: 'C:\temp'")]
        [ValidateNotNullOrEmpty()]
        [string]
        $MockDataOutputPath = 'C:\temp'
    )
    DynamicParam {
        if ($MockFunctionName) {
            $base = get-command $MockFunctionName -ErrorAction SilentlyContinue
        }
        if ($base) {
            $dict = new-object System.Management.Automation.RuntimeDefinedParameterDictionary
            $base.Parameters.GetEnumerator() | ForEach-Object {
                $val = $_.value
                $key = $_.key
                if ($key -notin [System.Management.Automation.Internal.CommonParameters].GetProperties().name) {
                    $param = New-Object System.Management.Automation.RuntimeDefinedParameter($key, $val.parameterType, $val.attributes)
                    $dict.add($key, $param)
                }
            }
            return $dict
        }
    }
    Begin {
        # Get a list of own parameters to exclude later
        $self = Get-Command Get-MockedData
        $selfParams = $self.parameters.keys | Where-Object {
            $_ -notin [System.Management.Automation.Internal.CommonParameters].GetProperties().name -and
            -not $self.parameters.$_.isdynamic
        }
    }
    Process {
        # Hashtable to hold valid parameters
        $splatParams = @{}

        # Remove own parameters
        $psboundparameters.keys | where-object {$_ -notin $selfParams} | ForEach-Object {
            $splatParams.add($_, $psboundparameters[$_])
        }

        $results = &$MockFunctionName @splatParams
        $Results | Export-Clixml "$MockDataOutputPath\$MockDataFunctionName.xml"
    }
}

You need to use the call operator & to indirectly call a function. 您需要使用调用运算符&间接调用函数。 In the second last line of your function put '&' before $MockFunctionName as in 在函数的第二行中,在$MockFunctionName之前$MockFunctionName '&', $MockFunctionName

  $Results = & $MockFunctionName $MockFunctionParameters

Parameters are trickier - there you should look at splatting to see how to pass parameters. 参数是麻烦-有你应该看看泼洒 ,以了解如何传递参数。

Finally, you might want to look at how Pester handles mocking . 最后,您可能想看看Pester如何处理嘲讽

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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