Using COM methods like [System.Runtime.InteropServices.Marshal]::GetActiveObject("VisualStudio.DTE") I can navigate the Visual Studio DTE object model fine. For instance from DTE object I can get Debugger, and then LocalProcesses, and the the Process object. But I need the derived Process2 interface on it, to call Attach2("<my debug engine>").
I could not find a way to obtain the interface I want, a simple cast results in runtime error: 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 Files\IIS Express\iisexpress.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
                You can't really, at least not in a way that PowerShell will be able to remember when it comes to member binding.
PowerShell only ever operates based on runtime information.  Even if you cast it in C# first, if QueryInterface returns the same pointer for that interface then all PowerShell is going to see is the IDispatch it currently detects.  Even if the object you obtained was a strongly typed version from the primary interop assembly, PowerShell only sees concrete types (which there doesn't seem to be one for Process2).
As a workaround, you can use reflection:
[EnvDTE80.Process2].InvokeMember(
    'Attach2',
    [Reflection.BindingFlags]::InvokeMethod,
    <# binder: #> $null,
    <# target: #> $process,
    <# args: #> @($myEngine))
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With