7

我正在尝试在包管理器控制台中使用 powershell 来编写从解决方案中删除项目的脚本,但我遇到了令人惊讶的困难。

我可以很容易地添加一个项目

PM> $dte.Solution.AddFromFile("C:\Dev\Project1.csproj")

现在我想删除一个项目,但什么也做不了。

我尝试了很多事情,包括:

PM> $project1 = Get-Project "Project1Name"
PM> $dte.Solution.Remove($project1)>

无法将参数“0”,值为:“System.__ComObject”,“删除”转换为
键入“EnvDTE.Project”:“无法转换类型的“System.__ComObject”值
“System.__ComObject#{866311e6-c887-4143-9833-645f5b93f6f1}”键入
“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'.

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

4

2 回答 2

5

是的,我知道我迟到了,但我刚刚为我们一直在编写的内部 NuGet 包解决了同样的问题,我想我已经找到了解决方法。

事实上,微软已经(有帮助地)未实现Delete 方法,并且正如我们都发现的那样,尝试在Solution2接口上调用Remove方法会根据上下文抛出令人兴奋的无数错误!

然而,我发现直接调用在SolutionClass中定义的Remove方法确实有效(尽管它被 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,因此将其传递给 aEnvDTE._SolutionEnvDTE80.Solution2会引发Type mismatch错误,因此很遗憾,您无法$solution通过 cmdlet 获取对象Get-Interface(这通常是我的首选方法)。[EnvDTE.SolutionClass]尽可能地进行演员阵容显然是可取的,但我再次发现这样做取得了不同程度的成功。因此上面略显草率$solution = $dte.Solution

希望这对其他人有用!

于 2015-02-12T17:15:18.563 回答
1

看起来它是“删除”而不是“删除”。请参阅此MSDN 文章

Project prj = dte.Solution.Projects.Item(1);
prj.Delete();
于 2013-07-27T20:10:58.347 回答