2011-04-04 16 views
23

PowerShell'den adlandırılmış parametreler kullanılarak COM yöntemi çağırmak mümkün mü? Ben ile çalışıyorum COM nesnesi yöntemi parametrelerinin onlarca vardır:PowerShell'den karmaşık bir COM yöntemi nasıl çağrılır?

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) 

bu parametrelerin çoğu isteğe bağlıdır ve bazıları birbirini dışlar. Win32com modülünü kullanarak Visual Basic veya Python'da, yalnızca gereksinim duyduğunuz seçeneklerin alt kümesini belirtmek için adlandırılmış parametreleri kullanabilirsiniz. (Python) Örneğin:

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) 

Ben aynı şekilde PowerShell bu nesneyi aramak anlamaya olamaz.

+1

Çok zor bir soruyla ilgili sorularınız için. Son çare çözümüm var. Ama önce, kıvrılıp kıvrılmak için kendimi ağlaman için bir dolaba gideceğim. – JasonMArcher

cevap

30

Bu sorun beni ilgilendirdi, bu yüzden bazı gerçek kazma yaptım ve bir çözüm buldum (ancak bazı basit durumlarda test ettim)!

kavramı anahtar çözelti onun aşırı birinde parametre adları geçmesine izin veren [System.Type]::InvokeMember kullanan

.

İşte temel kavram.

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

Çözüm Burada

adlandırılmış parametreleri ile yöntemlerini çağırmak için yeniden kullanılabilir bir çözümdür. Bu sadece COM nesneleri değil, herhangi bir nesne üzerinde çalışmalıdır. Parametrelerden biri olarak bir hashtable yaptım, böylece adlandırılmış parametreleri belirtmek daha doğal ve umarım daha az hataya yatkın olacaktır. İsterseniz de -Argument parametreyi adlı parametrelerle bir yöntemi çağırma

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

Örnekler

kullanarak parametre adları olmadan bir yöntemini çağırabilirsiniz.

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

## the syntax for more than one would be @{"First"="foo";"Second"="bar"} 

hiçbir parametre alır bir yöntemi çağırma (ayrıca $ null -Argument kullanabilirsiniz).

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

Bu harika bir çözümdür. – klumsy

+0

Vay. Teşekkürler. Bunu yarın test edeceğim. – David

+0

İyi iş, Jason. – x0n

İlgili konular