Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call a complex COM method from PowerShell?

Tags:

powershell

com

Is it possible to call a COM method from PowerShell using named parameters? The COM object method I am working with has dozens of parameters:

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 ) 

Most of those parameters are optional and some of them are mutually exclusive. In Visual Basic or Python using the win32com module you can use named parameters to specify only the subset of options you need. For example (in 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) 

I can't figure out how to call this object from PowerShell in the same way.

like image 584
David Avatar asked Apr 04 '11 22:04

David


People also ask

How do you call a method in PowerShell?

To perform or "invoke" a method of an object, type a dot (.), the method name, and a set of parentheses "()". If the method has arguments, place the argument values inside the parentheses. The parentheses are required for every method call, even when there are no arguments.

What is @{} in PowerShell?

@{} in PowerShell defines a hashtable, a data structure for mapping unique keys to values (in other languages this data structure is called "dictionary" or "associative array"). @{} on its own defines an empty hashtable, that can then be filled with values, e.g. like this: $h = @{} $h['a'] = 'foo' $h['b'] = 'bar'


1 Answers

This problem did interest me, so I did some real digging and I have found a solution (though I have only tested on some simple cases)!

Concept

The key solution is using [System.Type]::InvokeMember which allows you to pass parameter names in one of its overloads.

Here is the basic concept.

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

Solution

Here is a reusable solution for calling methods with named parameters. This should work on any object, not just COM objects. I made a hashtable as one of the parameters so that specifying the named parameters will be more natural and hopefully less error prone. You can also call a method without parameter names if you want by using the -Argument parameter

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             )         }     } } 

Examples

Calling a method with named parameters.

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

Calling a method that takes no parameters (you can also use -Argument with $null).

$shell = New-Object -ComObject Shell.Application Invoke-NamedParameter $Shell "MinimizeAll" @{} 
like image 145
JasonMArcher Avatar answered Sep 28 '22 17:09

JasonMArcher