Как вызвать сложный COM-метод из PowerShell?
Можно ли вызвать метод COM из PowerShell, используя именованные параметры? Метод COM-объекта, с которым я работаю, имеет десятки параметров:
object.GridData( DataFile, xCol, yCol, zCol, ExclusionFilter, DupMethod, xDupTol,
yDupTol, NumCols, NumRows, xMin, xMax, yMin, yMax, Algorithm, ShowReport,
SearchEnable, SearchNumSectors, SearchRad1, SearchRad2, SearchAngle,
SearchMinData, SearchDataPerSect, SearchMaxEmpty, FaultFileName, BreakFileName,
AnisotropyRatio, AnisotropyAngle, IDPower, IDSmoothing, KrigType, KrigDriftType,
KrigStdDevGrid, KrigVariogram, MCMaxResidual, MCMaxIterations, MCInternalTension,
MCBoundaryTension, MCRelaxationFactor, ShepSmoothFactor, ShepQuadraticNeighbors,
ShepWeightingNeighbors, ShepRange1, ShepRange2, RegrMaxXOrder, RegrMaxYOrder,
RegrMaxTotalOrder, RBBasisType, RBRSquared, OutGrid, OutFmt, SearchMaxData,
KrigStdDevFormat, DataMetric, LocalPolyOrder, LocalPolyPower, TriangleFileName )
Большинство из этих параметров являются необязательными, а некоторые являются взаимоисключающими. В Visual Basic или Python с использованием модуля win32com вы можете использовать именованные параметры, чтобы указать только поднабор параметров, которые вам нужны. Например (в Python):
Surfer.GridData(DataFile=InFile,
xCol=Options.xCol,
yCol=Options.yCol,
zCol=Options.zCol,
DupMethod=win32com.client.constants.srfDupMedZ,
xDupTol=Options.GridSpacing,
yDupTol=Options.GridSpacing,
NumCols=NumCols,
NumRows=NumRows,
xMin=xMin,
xMax=xMax,
yMin=yMin,
yMax=yMax,
Algorithm=win32com.client.constants.srfMovingAverage,
ShowReport=False,
SearchEnable=True,
SearchRad1=Options.SearchRadius,
SearchRad2=Options.SearchRadius,
SearchMinData=5,
OutGrid=OutGrid)
Я не могу понять, как вызвать этот объект из PowerShell таким же образом.
2 ответа
Эта проблема меня заинтересовала, поэтому я немного покопался и нашел решение (хотя я тестировал только на некоторых простых случаях)!
концепция
Ключевое решение использует [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" @{}
Использование функции Invoke-NamedParameter у меня не сработало. Мне удалось найти здесь интересное решение https://community.idera.com/database-tools/powershell/ask_the_experts/f/powershell_for_windows-12/6361/excel-spreadsheet-export, которое сработало для меня.
$excel = New-Object -ComObject excel.application
$objMissingValue = [System.Reflection.Missing]::Value
$Workbook = $excel.Workbooks.Open($datafile,$objMissingValue,$False,$objMissingValue,$objMissingValue,$objMissingValue,$true,$objMissingValue)
Любой параметр, который я не использовал, я добавил недостающее значение.