Visual Studio - 后期构建事件 - 抛出错误

16

我有一个漂亮的PowerShell驱动的后构建脚本,可以在编译完成后将所有插件拉入正确的位置,并解决它们与解决方案主项目的依赖关系。

我的问题是,偶尔当我做一些愚蠢的事情时,我可能会处于无法正确执行操作的状态,会在powershell中抛出异常并详细说明出了什么问题。

是否有一种方法可以使这些异常上升到Visual Studio错误窗口,以便当我的后构建失败时,vstudio会收到失败通知并在窗口中与所有其他警告/错误一起漂亮地格式化呈现?

编辑:这是对我理想情况的澄清。

已删除不可用的ImageShack链接

注意:如果您想知道如何在Visual Studio中显示自定义错误消息(当您控制错误消息时),您可以查看Roy Tinker的答案 以了解如何调整消息以显示出来。如果您感兴趣捕获无法控制的意外错误或寻找更完整的解决方案,请参见接受的答案。

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 中运行构建时可能出现的任何错误、警告或消息的输出窗口。


4
非常有帮助,感谢你花时间解决问题。这让我的发布构建步骤变得更好了。 - Pete Magsig
这里有一些类似于官方规范的东西,来自Catalin Sindelaru的(可能已被删除的)答案。参考链接:http://blogs.msdn.com/b/msbuild/archive/2006/11/03/msbuild-visual-studio-aware-error-messages-and-message-formats.aspx - Jeffrey Bosboom

13

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

使用exit()终止PowerShell进程

要从脚本返回状态代码,如果为非零,则会显示在错误列表中,请使用以下内容:

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

这并不完全将错误文本添加到您的错误列表中,但它确实终止了脚本,并在错误列表中加入了一些内容,指示哪个预先或后置构建命令失败了。

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

我花了一点时间研究如何在MSBuild任务中执行PowerShell脚本的细节。我在我的博客上发布了一个包含示例代码的完整文章。请查看它,因为它包括更多讨论和有关如何处理示例项目的说明。它可能不是一个完整或完美的解决方案,但我用一个非常简单的脚本在我的机器上工作了。

这种方法提供了在报告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属性记录错误。完成后关闭runspace,并返回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文件)。在后期生成事件中集成任务只需要几个步骤。

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

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

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

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

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

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

屏幕截图


@kbrimington - 不知道如何让消息显示出来吗? - Aren
@Aren - 你可以在构建宏或自定义MSBuild任务中运行PowerShell运行时,但我不确定如何建议您开始。 首先,请尝试这些资源:用于宏- https://dev59.com/yEfRa4cB1Zd3GeqP9oO3,用于MSBuild任务- http://bartdesmet.net/blogs/bart/archive/2008/02/15/the-custom-msbuild-task-cookbook.aspx。祝你好运! - kbrimington
1
从技术角度来看,exit 不是别名而是关键字;然而,其效果与 Exit-PSSession 相同。 - Keith Hill
@kbrimington - 是的,我也注意到了 - 有点奇怪,但这不会是我在文档中发现的第一件奇怪的事情。 :-) - Keith Hill
@kbrimington - 哇,非常感谢您抽出时间深入回答我的问题,如果可以的话我会给您+50分的:o - Aren
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接