I'm trying to automate some code-related routines in VisualStudio 2017 using integrated Powershell console and VS Automation model (DTE). When I'm working on Solution/Project/File level, things are ok, e.g.
PS> $dte.ActiveDocument.ProjectItem
IsDirty : False
FileCount : 1
Name : FeaturesComposition.cs
Collection : System.__ComObject
Properties : System.__ComObject
DTE : System.__ComObject
Kind : {6BB5F8EE-4483-11D3-8BCF-00C04F8EC28C}
ProjectItems : System.__ComObject
Object : System.__ComObject
ExtenderNames : {}
ExtenderCATID : {610D4615-D0D5-11D2-8599-006097C68E81}
Saved : True
ConfigurationManager :
FileCodeModel : System.__ComObject
Document : System.__ComObject
SubProject :
ContainingProject : System.__ComObject
But when I come to the code model of some particular file, there is nothing to work with:
PS> $dte.ActiveDocument.ProjectItem.FileCodeModel | Format-List -Property *
System.__ComObject
PS> $dte.ActiveDocument.ProjectItem.FileCodeModel | gm
PS>
Is it possible to get access to such submodels? Is there any easy way of dispatching EnvDTE.DTE interface to the existing $dte instance? I've tried some ideas below, but without no success.
Add-Type -Path "$env:VSAPPIDDIR\PublicAssemblies\envdte.dll"
PS> # Explicit cast doesn't work
PS> [EnvDTE.DTE]$dte
[ERROR] Cannot convert the "System.__ComObject" value of type "System.__ComObject#{04a72314-32e9-48e2-9b87-a63603454f3e}" to type "EnvDTE.DTE".
PS> # Wrapper works but it's useless
PS> $wrapped = [Runtime.InteropServices.Marshal]::CreateWrapperOfType($dte, [EnvDTE.DTEClass])
PS> $wrapped.ActiveDocument.ProjectItem.FileCodeModel
System.__ComObject
PS> # GetComInterfaceForObject gives the same IntPtr as IUnknown:QueryInterface
PS> # different from the call to GetComInterfaceForObject for example,
PS> # so I hoped to get another casting results. But it is the same.
PS> $contract = [Runtime.InteropServices.Marshal]::GetComInterfaceForObject($dte, [EnvDTE.DTE])
PS> [EnvDTE.DTE][Runtime.InteropServices.Marshal]::GetObjectForIUnknown($contract)
[ERROR] Cannot convert the "System.__ComObject" value of type "System.__ComObject#{04a72314-32e9-48e2-9b87-a63603454f3e}" to type "EnvDTE.DTE".
Try this:
$fileCodeModel = Get-Interface $dte.ActiveDocument.ProjectItem.FileCodeModel ([ENVDTE80.FileCodeModel2])