Visual Studio - 发布后事件 - 抛出错误

Are*_*ren 15 powershell post-build-event visual-studio

我有一个很好的power-shell驱动的后期构建脚本,它可以完成一些神奇的mumbo-jumbo,用于在编译完成后将所有插件拉到正确的位置,并使用解决方案的主项目来整理它们的依赖项.

我的问题是,偶尔当我做一些愚蠢的事情时,我最终会处于一种状态,我的脚本无法正确执行它的操作,并在powershell中抛出一个异常,其中包含错误的详细信息.

有没有办法让这些异常进入Visual Studio Error窗口,这样当我的post-build失败时,vstudio会收到失败通知,并在窗口中将其与所有其他警告/错误一起很好地格式化?

编辑:这是对我正在寻找的东西的澄清.

删除了死的ImageShack链接

注意:如果您已经登陆这里寻找如何在Visual Studio中显示自定义错误消息(当您控制错误消息时),您可以看到Roy Tinker的答案,了解如何定制您的消息以显示.如果您对捕获意外错误感兴趣而无法控制,或者找到更完整的解决方案,请参阅接受的答案.

Roy*_*ker 18

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

FilePath[(LineNumber[,ColumnNumber])]: MessageType[ MessageCode]: Description
Run Code Online (Sandbox Code Playgroud)

举个例子:

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

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

  • 这非常有帮助.感谢您抽出宝贵的时间来解决这个问题.刚刚使我的帖子构建步骤更好. (3认同)

kbr*_*ton 11

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

使用exit()终止PowerShell进程

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

exit(45) # or any other non-zero number, for that matter.
Run Code Online (Sandbox Code Playgroud)

这并不能将错误文本精确地放到错误列表中,但它会终止脚本并在错误列表中获取一些内容,以指示构建前或构建后命令失败.

使用自定义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()
    {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

在该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;
Run Code Online (Sandbox Code Playgroud)

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

例如,考虑一个基于C#的类库项目(.csproj).在post build事件中集成任务只需要几件事.

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

<UsingTask TaskName="PsBuildTask"
           AssemblyFile="..\Noc.PsBuild\bin\Debug\Noc.PsBuild.dll" />
Run Code Online (Sandbox Code Playgroud)

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

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

<Target Name="AfterBuild">
    <PsBuildTask ScriptPath=".\script.ps1" />
</Target>
Run Code Online (Sandbox Code Playgroud)

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

截图