通过Package Manager Console从解决方案中删除项目

时间:2013-07-21 05:02:13

标签: visual-studio powershell automation nuget envdte

我正在尝试在程序包管理器控制台中使用powershell来编写从解决方案中删除项目的脚本,并且我遇到了非常困难的时间。

我可以通过

轻松添加项目
PM> $dte.Solution.AddFromFile("C:\Dev\Project1.csproj")

现在我想要删除一个项目,但无法正常工作。

我尝试过很多方面,包括:

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'.

我尝试了其他组合,但我显然在转动轮子。我很感激任何建议。

2 个答案:

答案 0 :(得分:5)

是的,我知道我已经迟到了,但我刚刚为我们写过的内部NuGet包解决了同样的问题,我想我已经找到了怎么做。

事实上,微软已经(帮助)离开了删除方法unimplemented,正如我们发现的那样,尝试在Remove界面上调用Solution2方法会引发令人兴奋的无数错误视情况而定!

然而,我发现直接调用Remove中定义的SolutionClass方法确实有效(尽管它被Microsoft记录为内部使用。但是,嘿,当其他所有选项都用尽时...)。唯一的问题是运行时绑定程序有时似乎无法解决方法重载,从而产生错误:

No overload for method 'Remove' takes 1 arguments

所有这些都意味着是时候把我们的反射蜡笔拿出来了!代码如下所示:

$removeMethod = [EnvDTE.SolutionClass].GetMethod("Remove");
$solution = $dte.Solution;
$toremove = ($solution.Projects | where ProjectName -eq "<whatever>");
$removeMethod.Invoke($solution, @($toremove));

经过一天的各种迭代(许多与问题中的那些非常相似)和不同程度的成功(取决于我是在包管理器内执行,从安装脚本内部还是在调试器内执行),上面是什么我发现最可靠。

需要注意的一点是,因为反映的方法在EnvDTE.SolutionClass中定义,传递EnvDTE._SolutionEnvDTE80.Solution2会引发Type mismatch错误,所以很遗憾您无法获取$solution cmdlet(通常是我首选的方法)的Get-Interface对象。尽可能在[EnvDTE.SolutionClass]进行投射显然是可取的,但我再次发现这样做有不同程度的成功。因此上面略显草率$solution = $dte.Solution

希望这对其他人有用!

答案 1 :(得分:1)

看起来像是“删除”而不是“删除”。见MSDN article

Project prj = dte.Solution.Projects.Item(1);
prj.Delete();