如何在PowerShell中从COM对象中删除不同的接口



使用像[System.Runtime.InteropServices.Marshal]::GetActiveObject("VisualStudio.DTE")这样的COM方法,我可以很好地导航Visual Studio DTE对象模型。例如,从DTE对象中,我可以获得Debugger,然后是LocalProcessesProcess对象。但我需要它上的派生Process2接口来调用Attach2("<my debug engine>")。我找不到获得我想要的接口的方法,一个简单的强制转换导致运行时错误:Cannot convert the "System.__ComObject" value of type "System.__ComObject#{5c5a0070-f396-4e37-a82a-1b767e272df9}" to type "EnvDTE80.Process2"

PS> $dte = [System.Runtime.InteropServices.Marshal]::GetActiveObject("VisualStudio.DTE")
PS> $p = $dte.Debugger.LocalProcesses | where {$_.ProcessID -eq 11212}
PS> $p

Name       : C:Program FilesIIS Expressiisexpress.exe
ProcessID  : 11212
Programs   : System.__ComObject
DTE        : System.__ComObject
Parent     : System.__ComObject
Collection : System.__ComObject

PS> [EnvDTE80.Process2]$p2 = $p
Cannot convert the "System.__ComObject" value of type "System.__ComObject#{5c5a0070-f396-4e37-a82a-1b767e272df9}" to type "EnvDTE80.Process2".
At line:1 char:1
+ [EnvDTE80.Process2]$p2 = $p
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : MetadataError: (:) [], ArgumentTransformationMetadataException
+ FullyQualifiedErrorId : RuntimeException

当涉及到成员绑定时,你真的不能,至少不能以PowerShell能够记住的方式。

PowerShell仅根据运行时信息运行。即使您先在C#中强制转换它,如果QueryInterface为该接口返回相同的指针,那么PowerShell将看到的所有指针都是它当前检测到的IDispatch。即使您获得的对象是来自主互操作程序集的强类型版本,PowerShell也只能看到具体类型(Process2似乎没有具体类型(。

作为一种变通方法,您可以使用反射:

[EnvDTE80.Process2].InvokeMember(
'Attach2',
[Reflection.BindingFlags]::InvokeMethod,
<# binder: #> $null,
<# target: #> $process,
<# args: #> @($myEngine))

最新更新