如何从 PowerShell 调用复杂的 COM 方法?
Posted
技术标签:
【中文标题】如何从 PowerShell 调用复杂的 COM 方法?【英文标题】:How to call a complex COM method from PowerShell? 【发布时间】:2011-07-29 12:38:32 【问题描述】:是否可以使用命名参数从 PowerShell 调用 COM 方法?我正在使用的 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 )
这些参数中的大多数是可选的,其中一些是互斥的。在使用 win32com 模块的 Visual Basic 或 Python 中,您可以使用命名参数仅指定您需要的选项子集。例如(在 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】:这个问题确实让我感兴趣,所以我进行了一些真正的挖掘并找到了解决方案(虽然我只测试了一些简单的案例)!
概念
关键解决方案是使用[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" @
【讨论】:
哇。谢谢。明天我会测试一下。 不错!这是在 GitHub 上还是什么的?我很想窃取你的代码并引用一个实际的 repo。 ;)【参考方案2】:使用 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)
我没有使用的任何参数都添加了缺失值。
【讨论】:
以上是关于如何从 PowerShell 调用复杂的 COM 方法?的主要内容,如果未能解决你的问题,请参考以下文章
如何从其他powershell脚本调用powershell脚本并且脚本是在powershell对象而不是文件中分配的
如何在 powershell 中调用 devenv.com? [复制]
如何使用 Powershell 进行复杂查询 MongoDB
如何从 C# 文件调试“调用”Powershell (ps1)