title: How to add files to an SSDT Visual Studio project from Powershell 7
body: <p>I'd like to automate adding/removing files to/from a SSDT (Database) Project in Powershell 7.</p>
  <p>My Solution has 3 SSDT Projects in it and is running in a VS 2019 instance.</p>
  <p>I can get the DTE object with help from # <a href="https://stackoverflow.com/questions/64823199/is-there-a-substitue-for-system-runtime-interopservices-marshal-getactiveobject/64826127#64826127">Is there a substitue for System.Runtime.InteropServices.Marshal.GetActiveObject() in .NET Core?</a> along with the EnvDTE, EnvDTE80, EnvDTE90 and EnvDTE100 v16.10.31320.204 libraries from Nuget</p>
  <p>It feels like I need some more libraries though as I get all these impenetrable System.__ComObject's - but I cannot work out how to discover the libraries that I need.</p>
  <p>Here are the main sights I've seen on the journey so far:</p>
  <pre><code>&gt; $dte
  Name                   : Microsoft Visual Studio
  FileName               : C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\devenv.exe
  Version                : 16.0
  CommandBars            : System.__ComObject
  Windows                : System.__ComObject
  Events                 : System.__ComObject
  AddIns                 :
  MainWindow             : System.__ComObject
  ActiveWindow           : System.__ComObject
  DisplayMode            : 2
  Solution               : System.__ComObject
  Commands               : System.__ComObject
  SelectedItems          : System.__ComObject
  CommandLineArguments   : &quot;C:\Users\bgerhardi\source\Vega\VegaDW\src\VegaDW-DBs.sln&quot;
  DTE                    : System.__ComObject
  LocaleID               : 1033
  WindowConfigurations   : System.__ComObject
  Documents              : System.__ComObject
  ActiveDocument         : System.__ComObject
  Globals                : System.__ComObject
  StatusBar              : System.__ComObject
  FullName               : C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\devenv.exe
  UserControl            : True
  ObjectExtenders        : System.__ComObject
  Find                   : System.__ComObject
  Mode                   : 1
  ItemOperations         : System.__ComObject
  UndoContext            : System.__ComObject
  Macros                 :
  ActiveSolutionProjects : {}
  MacrosIDE              :
  RegistryRoot           : Software\Microsoft\VisualStudio\16.0_cd071aac
  Application            : System.__ComObject
  ContextAttributes      : System.__ComObject
  SourceControl          : System.__ComObject
  SuppressUI             : False
  Debugger               : System.__ComObject
  Edition                : Enterprise
  
  </code></pre>
  <p>looking in the $env.Solution I can see a nice object and another bunch of System.__ComObject's</p>
  <pre><code>&gt; $dte.Solution
  System.__ComObject
  System.__ComObject
  System.__ComObject
  
  Name                 : Miscellaneous Files
  FileName             :
  IsDirty              : False
  Collection           :
  DTE                  : System.__ComObject
  Kind                 : {66A2671D-8FB5-11D2-AA7E-00C04F688DDE}
  ProjectItems         : System.__ComObject
  Properties           :
  UniqueName           : &lt;MiscFiles&gt;
  Object               :
  ExtenderNames        : {}
  ExtenderCATID        : {610d4612-d0d5-11d2-8599-006097c68e81}
  FullName             :
  Saved                : True
  ConfigurationManager :
  Globals              :
  ParentProjectItem    :
  CodeModel            :
  </code></pre>
  <p>However I don't see this Miscellanous Files item in the VS UI.</p>
  <p>If I try to go into these, strangely there is nothing in 0 but just these impenetrable System.__ComObject's</p>
  <pre><code>&gt; $dte.Solution[0]
  OperationStopped: Value does not fall within the expected range.
  
  &gt; $dte.Solution[1]
  System.__ComObject
  
  &gt; $dte.Solution[1] | gm 
  
  &gt;
  </code></pre>
  <p>I've tried casting to a few differnet things but all tell me a (COM?) GUID that I can't find anywhere in my registry or on the internet</p>
  <pre><code>&gt; [EnvDTE.Project]$dte.Solution[1]
  InvalidArgument: Cannot convert the &quot;System.__ComObject&quot; value of type &quot;System.__ComObject#{2aa7b615-65c8-356e-8652-98f68ab7548e}&quot; to type &quot;EnvDTE.Project&quot;.
  </code></pre>
  <p>What is the right way to navigate my way through these __ComObject's and find the correct Types that I need?</p>
  <p>To create a repro for this on your own machine, simply</p>
  <ul>
  <li>create a new &quot;SQL Server Database Project&quot; in Visual Studio 2019. It behaves the same way for me - impenetrable System.__ComObject's</li>
  </ul>
  <p><a href="https://i.stack.imgur.com/wjK3P.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/wjK3P.png" alt="Create new project" /></a></p>
  <ul>
  <li>Run PS7 instance</li>
  <li>run the following
  <pre><code>
   $methoddef = 'public static object GetActiveObject(string progId, bool throwOnError = false)
   {
       if (progId == null)
           throw new ArgumentNullException(nameof(progId));
  
       var hr = CLSIDFromProgIDEx(progId, out var clsid);
       if (hr &lt; 0)
       {
           if (throwOnError)
               Marshal.ThrowExceptionForHR(hr);
  
           return null;
       }
  
       hr = GetActiveObject(clsid, IntPtr.Zero, out var obj);
       if (hr &lt; 0)
       {
           if (throwOnError)
               Marshal.ThrowExceptionForHR(hr);
  
           return null;
       }
       return obj;
   }
  
   [DllImport(&quot;ole32&quot;)]
   private static extern int CLSIDFromProgIDEx([MarshalAs(UnmanagedType.LPWStr)] string lpszProgID, out Guid lpclsid);
  
   [DllImport(&quot;oleaut32&quot;)]
   private static extern int GetActiveObject([MarshalAs(UnmanagedType.LPStruct)] Guid rclsid, IntPtr pvReserved, [MarshalAs(UnmanagedType.IUnknown)] out object ppunk);'
  
   $blah = add-type -MemberDefinition $methoddef -Name &quot;Blah&quot; -Namespace &quot;Blah&quot; -PassThru
   $dte = $blah::GetActiveObject('VisualStudio.DTE.16.0')
  
  </code></pre>
  </li>
  <li>notice that <code>$dte.ActiveSolutionProjects[0]</code> returns nothing useful, just System.__ComObject</li>
  </ul>