Remove project from solution via Package Manager Console
Asked Answered
F

2

7

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.

Founder answered 21/7, 2013 at 5:2 Comment(1)
Did you get this working? I have a similar need.Catastrophe
G
6

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!

Gisser answered 12/2, 2015 at 17:15 Comment(1)
It was very useful to me! On some machines users still encountered Exception calling "Invoke" with "2" argument(s): "Object does not match target type." ... MethodInvocationException ... TargetException. I resolved this by using [EnvDTE._Solution].GetMethod in place of [EnvDTE.SolutionClass].GetMethod.Whitewash
S
1

Looks like it is "Delete" instead of "Remove". See this MSDN article

Project prj = dte.Solution.Projects.Item(1);
prj.Delete();
Shawnna answered 27/7, 2013 at 20:10 Comment(1)
FTA: "Note that this method is not currently implemented."Overrun

© 2022 - 2024 — McMap. All rights reserved.