Как вызвать сложный COM-метод из PowerShell? - PullRequest
25 голосов
/ 05 апреля 2011

Можно ли вызвать метод 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 таким же образом.

1 Ответ

31 голосов
/ 07 апреля 2011

Эта проблема меня заинтересовала, поэтому я немного покопался и нашел решение (хотя я тестировал только на некоторых простых случаях)!

Концепция

Ключевое решение использует [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" @{}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...