¿Cómo llamar a un método COM complejo de PowerShell?

¿Es posible llamar a un método COM de PowerShell usando parámetros nombrados? El método de objeto COM con el que estoy trabajando tiene docenas de parámetros:

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 ) 

La mayoría de esos parámetros son opcionales y algunos de ellos son mutuamente excluyentes. En Visual Basic o Python utilizando el módulo win32com, puede usar parámetros con nombre para especificar solo el subconjunto de opciones que necesita. Por ejemplo (en 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) 

No puedo entender cómo llamar a este objeto desde PowerShell de la misma manera.

Este problema me interesó, así que hice una verdadera excavación y encontré una solución (¡aunque solo he probado en algunos casos simples)!

Concepto

La solución clave es usar [System.Type]::InvokeMember que le permite pasar nombres de parámetros en una de sus sobrecargas.

Aquí está el concepto básico.

 $Object.GetType().InvokeMember($Method, [System.Reflection.BindingFlags]::InvokeMethod, $null, ## Binder $Object, ## Target ([Object[]]$Args), ## Args $null, ## Modifiers $null, ## Culture ([String[]]$NamedParameters) ## NamedParameters ) 

Solución

Aquí hay una solución reutilizable para llamar a métodos con parámetros nombrados. Esto debería funcionar en cualquier objeto, no solo en los objetos COM. Hice una tabla hash como uno de los parámetros para que especificar los parámetros nombrados sea más natural y, con suerte, menos propenso a errores. También puede llamar a un método sin nombres de parámetros si lo desea utilizando el parámetro -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 ) } } } 

Ejemplos

Llamar a un método con parámetros nombrados.

 $shell = New-Object -ComObject Shell.Application Invoke-NamedParameter $Shell "Explore" @{"vDir"="$pwd"} ## the syntax for more than one would be @{"First"="foo";"Second"="bar"} 

Llamar a un método que no requiere parámetros (también puede usar -Argumento con $ null).

 $shell = New-Object -ComObject Shell.Application Invoke-NamedParameter $Shell "MinimizeAll" @{}