[英]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.