16

我有一个很好的 power-shell 驱动的构建后脚本,它可以在我们所有的插件编译后将它们拉到正确的位置,并使用解决方案的主项目整理它们的依赖关系。

我的问题是,有时当我做一些愚蠢的事情时,我最终可能会处于我的脚本无法正确执行它的操作的状态,并在 powershell 中引发异常,其中包含错误的详细信息。

有没有办法让这些异常出现在 Visual Studio 错误窗口中,这样当我的后期构建失败时,vstudio 会收到一个失败通知,并在窗口中很好地格式化它以及所有其他警告/错误?

编辑:这是对我理想中寻找的内容的澄清。

删除了无效的 ImageShack 链接

注意:如果您已登陆此处寻找如何在 Visual Studio 中显示自定义错误消息(当您可以控制错误消息时),您可以查看Roy Tinker 的回答以了解如何定制要显示的消息。如果您有兴趣捕捉无法控制的意外错误,或寻找更完整的解决方案,请参阅已接受的答案。

4

2 回答 2

19

要创建将出现在“错误列表”窗口中的错误、警告或消息,只需从构建前或构建后事件启动的脚本中以下列格式将消息记录到 stdout 或 stderr。如果有官方规范,请评论或编辑;这只是我通过反复试验和观察 MSBuild 的输出能够推断出的。方括号表示“可选”:

FilePath[(LineNumber[,ColumnNumber])]: MessageType[ MessageCode]: Description

举个例子:

E:\Projects\SampleProject\Program.cs(18,5): error CS1519: Invalid token '}' in class, struct, or interface member declaration

有关更多示例,请参阅在 Visual Studio 中运行构建时可能出现的任何错误/警告/消息的输出窗口。

于 2013-01-04T21:32:19.760 回答
13

以下是在 PowerShell 脚本出错时中断构建的两种方法。

用于exit()终止 PowerShell 进程

要从脚本返回状态代码,如果该代码非零,将显示在错误列表中,请使用以下命令:

exit(45) # or any other non-zero number, for that matter.

这并不能准确地将错误文本添加到您的错误列表中,但它会终止脚本并在您的错误列表中获取一些内容以指示哪个构建前或构建后的命令失败。

使用自定义 MSBuild 任务执行 PowerShell 脚本

我花了一点时间研究在 MSBuild 任务中执行 PowerShell 脚本的细节。我的博客上有一篇带有示例代码的完整文章。请检查一下,因为它包含更多讨论,以及如何处理示例项目的一些解释。这可能不是一个完整或完美的解决方案,但我通过一个非常简单的脚本在 My Machine TM上完成了它。

这种方法在报告 PowerShell 错误时提供行和列精度,甚至支持我们在 Visual Studio 中习惯的双击文件行为。如果缺少它,我相信您将能够扩展它以满足您的需求。此外,根据您的 Visual Studio 版本,您可能需要查看程序集参考版本等详细信息。

首先,在类库项目中构建自定义 MSBuild 任务。该库应引用以下用于 MSBuild 和 PowerShell 集成的程序集。(请注意,此示例需要 PowerShell 2.0。)

  • Microsoft.Build.Framework (GAC)
  • Microsoft.Build.Utilities.v3.5 (GAC)
  • System.Management.Automation(来自 C:\Program Files\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0)

构建一个任务类,并公开一个属性来指定 PowerShell 脚本的路径,如下所示:

using System.IO;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

public class PsBuildTask : Task
{
    [Required]
    public string ScriptPath { get; set; }

    public override bool Execute()
    {
        // ...
    }
}

在该Execute()方法中,启动 PowerShell 运行时、执行脚本并收集错误。使用该Log属性记录错误。完成后,关闭运行空间,如果脚本没有记录错误则返回 true。

// create Powershell runspace
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();

// create a pipeline and feed it the script text
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(". " + ScriptPath);

// execute the script and extract errors
pipeline.Invoke();
var errors = pipeline.Error;

// log an MSBuild error for each error.
foreach (PSObject error in errors.Read(errors.Count))
{
    var invocationInfo = ((ErrorRecord)(error.BaseObject)).InvocationInfo;
    Log.LogError(
        "Script",
        string.Empty,
        string.Empty,
        new FileInfo(ScriptPath).FullName,
        invocationInfo.ScriptLineNumber,
        invocationInfo.OffsetInLine,
        0,
        0,
        error.ToString());
}

// close the runspace
runspace.Close();

return !Log.HasLoggedErrors;

就是这样。有了这个程序集,我们可以配置另一个项目来使用 MSBuild 任务。

例如,考虑一个基于 C# 的类库项目 (.csproj)。将任务集成到构建后事件中只需要几件事。

首先,<Project>在 .csproj 文件的节点内注册任务,如下所示:

<UsingTask TaskName="PsBuildTask"
           AssemblyFile="..\Noc.PsBuild\bin\Debug\Noc.PsBuild.dll" />

TaskName 应该是任务类的名称,但似乎不需要命名空间。AssemblyFile是自定义 MSBuild 任务程序集的绝对路径,或相对于 .csproj 文件的相对路径。对于 GAC 中的程序集,您可以改用该AssemblyName属性。

注册后,该任务可以在构建前和构建后事件中使用。<Project>在 .csproj 文件的元素中配置构建事件,如下所示:

<Target Name="AfterBuild">
    <PsBuildTask ScriptPath=".\script.ps1" />
</Target>

就是这样。当 Visual Studio 编译项目时,它会加载自定义程序集和任务对象并执行任务。检索并报告管道引发的错误。

截屏

于 2010-09-13T21:32:11.400 回答