I am trying to use powershell within the Package Manager Console to script the removal of a project from a solution and I am having a surprisingly hard time.
I can easily add a project by
PM> $dte.Solution.AddFromFile("C:\Dev\Project1.csproj")
Now I want to be remove a project and can't get anything to work.
I have tried a number of things including:
PM> $project1 = Get-Project "Project1Name"
PM> $dte.Solution.Remove($project1)
>
Cannot convert argument "0", with value: "System.__ComObject", for "Remove" to
type "EnvDTE.Project": "Cannot convert the "System.__ComObject" value of type
"System.__ComObject#{866311e6-c887-4143-9833-645f5b93f6f1}" to type
"EnvDTE.Project"."
PM> $project = Get-Interface $project1 ([EnvDTE.Project])
PM> $dte.Solution.Remove($project)
Cannot convert argument "0", with value: "System.__ComObject", for "Remove" to
type "EnvDTE.Project": "Cannot convert the "System.__ComObject" value of type
"NuGetConsole.Host.PowerShell.Implementation.PSTypeWrapper" to type
"EnvDTE.Project"."
PM> $project = [EnvDTE.Project] ($project1)
Cannot convert the "System.__ComObject" value of type
"System.__ComObject#{866311e6-c887-4143-9833-645f5b93f6f1}" to type
"EnvDTE.Project".
PM> $solution2 = Get-Interface $dte.Solution ([EnvDTE80.Solution2])
PM> $solution2.Remove($project1)
Exception calling "Remove" with "1" argument(s): "Exception calling
"InvokeMethod" with "3" argument(s): "Object must implement IConvertible.""
PM> $dte2 = Get-Interface $dte ([EnvDTE80.DTE2])
PM> $dte2.Solution.Remove($project)
Method invocation failed because [System.Object[]] doesn't contain a method
named 'Remove'.
I have tried other combinations, but I am clearly spinning my wheels. I appreciate any suggestions.
Right, I know I'm late to the party but I've just been tackling this same issue for an internal NuGet package we've been writing, and I think I've found how to do it.
Indeed Microsoft have (helpfully) left the Delete method unimplemented, and as we have both found, attempting to call the Remove method on the Solution2 interface throws an exciting myriad of errors depending on context!
However what I have found is that directly invoking the Remove method defined in SolutionClass does actually work (despite its being documented by Microsoft as internal use only. But hey, when every other option is exhausted...). The only catch is that the runtime binder also sometimes seems to fail to resolve the method overload, producing the error:
No overload for method 'Remove' takes 1 arguments
All of which means that it's time to get our reflection crayons out! The code looks like this:
$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 closely resembling those in the question) and varying degrees of success (depending on whether I was executing inside the package manager, from inside the install script or within a debugger), the above is what I have found to be most reliable.
One thing to note is that because the reflected method is defined in EnvDTE.SolutionClass
, passing it a EnvDTE._Solution
or EnvDTE80.Solution2
throws a Type mismatch
error, so unfortunately you cannot obtain your $solution
object by the Get-Interface
cmdlet (which is usually my preferred method). Doing the cast to [EnvDTE.SolutionClass]
wherever possible is obviously preferable, but again I've found varying degrees of success in doing so. Hence the slightly sloppy $solution = $dte.Solution
above.
Hope this is useful to someone else!
Looks like it is "Delete" instead of "Remove". See this MSDN article
Project prj = dte.Solution.Projects.Item(1);
prj.Delete();
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