That's right, I know I'm late for the party, but I just addressed the same issue for the internal NuGet package we are writing, and I think I found how to do it.
Indeed, Microsoft (using) left the Delete unimplemented method, and, as we both discovered, an attempt to call Remove on the Solution2 interface produces an exciting array of errors depending on the context!
However, I found that I directly called the Remove method defined in SolutionClass really works (despite the fact that Microsoft is only documented as internal use. But when every other option has been exhausted ...). The only catch is that the run-time middleware sometimes also cannot resolve the method overload, creating an error:
No overload for method 'Remove' takes 1 arguments
All this means it's time to get our reflective pencils! The code is as follows:
$removeMethod = [EnvDTE.SolutionClass].GetMethod("Remove"); $solution = $dte.Solution; $toremove = ($solution.Projects | where ProjectName -eq "<whatever>"); $removeMethod.Invoke($solution, @($toremove));
After a day of various iterations (many of which are very similar to questions) and with varying degrees of success (depending on whether I was running inside the package manager, inside the script installation or inside the debugger), the above is what I found the most reliable.
It should be noted that since the reflected method is defined in EnvDTE.SolutionClass , passing it to EnvDTE._Solution or EnvDTE80.Solution2 throws a Type mismatch error, so, unfortunately, you cannot get your $solution object using Get-Interface (which is usually mine preferred method). Obviously, casting to [EnvDTE.SolutionClass] , if possible, preferable, but again I found a variable degree of success in this. Therefore, a bit sloppy $solution = $dte.Solution higher.
Hope this is helpful to someone else!