Ответ 1
Эта проблема интересовала меня, поэтому я действительно немного поработал, и я нашел решение (хотя я тестировал только в некоторых простых случаях)!
Концепция
Ключевое решение использует [System.Type]::InvokeMember
, который позволяет передавать имена параметров в одной из своих перегрузок.
Вот базовая концепция.
$Object.GetType().InvokeMember($Method, [System.Reflection.BindingFlags]::InvokeMethod,
$null, ## Binder
$Object, ## Target
([Object[]]$Args), ## Args
$null, ## Modifiers
$null, ## Culture
([String[]]$NamedParameters) ## NamedParameters
)
Решение
Вот многоразовое решение для вызова методов с именованными параметрами. Это должно работать на любом объекте, а не только на COM-объектах. Я сделал хэш-таблицу в качестве одного из параметров, так что указание названных параметров будет более естественным и, надеюсь, меньше подвержено ошибкам. Вы также можете вызвать метод без имени параметра, если хотите, используя параметр -Argument
Function Invoke-NamedParameter {
[CmdletBinding(DefaultParameterSetName = "Named")]
param(
[Parameter(ParameterSetName = "Named", Position = 0, Mandatory = $true)]
[Parameter(ParameterSetName = "Positional", Position = 0, Mandatory = $true)]
[ValidateNotNull()]
[System.Object]$Object
,
[Parameter(ParameterSetName = "Named", Position = 1, Mandatory = $true)]
[Parameter(ParameterSetName = "Positional", Position = 1, Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]$Method
,
[Parameter(ParameterSetName = "Named", Position = 2, Mandatory = $true)]
[ValidateNotNull()]
[Hashtable]$Parameter
,
[Parameter(ParameterSetName = "Positional")]
[Object[]]$Argument
)
end { ## Just being explicit that this does not support pipelines
if ($PSCmdlet.ParameterSetName -eq "Named") {
## Invoke method with parameter names
## Note: It is ok to use a hashtable here because the keys (parameter names) and values (args)
## will be output in the same order. We don't need to worry about the order so long as
## all parameters have names
$Object.GetType().InvokeMember($Method, [System.Reflection.BindingFlags]::InvokeMethod,
$null, ## Binder
$Object, ## Target
([Object[]]($Parameter.Values)), ## Args
$null, ## Modifiers
$null, ## Culture
([String[]]($Parameter.Keys)) ## NamedParameters
)
} else {
## Invoke method without parameter names
$Object.GetType().InvokeMember($Method, [System.Reflection.BindingFlags]::InvokeMethod,
$null, ## Binder
$Object, ## Target
$Argument, ## Args
$null, ## Modifiers
$null, ## Culture
$null ## NamedParameters
)
}
}
}
<сильные > Примеры
Вызов метода с именованными параметрами.
$shell = New-Object -ComObject Shell.Application
Invoke-NamedParameter $Shell "Explore" @{"vDir"="$pwd"}
## the syntax for more than one would be @{"First"="foo";"Second"="bar"}
Вызов метода, который не принимает параметров (вы также можете использовать -Argument с $null).
$shell = New-Object -ComObject Shell.Application
Invoke-NamedParameter $Shell "MinimizeAll" @{}