如何在Visual Studio 2017 (C#)中抑制初始的构建后事件错误?

6

我在Visual Studio 2017中有一个C#解决方案。我还有一个名为foobar.bat的批处理脚本,其中包含以下代码:

echo foobar : error 1: This is a test error.           

我的目标是在构建特定项目时,只让测试错误信息出现在Visual Studio的错误列表中,并且当它出现时停止构建。因此,我将[脚本路径]\foobar.bat放入项目的后期构建事件命令行中,然后进行构建。现在,在Visual Studio的错误列表中,我得到了两条错误消息:

  1. "[脚本路径]\foobar.bat" 命令已退出并带有代码-1。
  2. This is a test error.

在这种情况下,看到第一条只打印出我的后期构建事件内容的错误消息没有用。我想要抑制这个初始错误,以便只显示我的自定义错误消息(或者至少将其更改为更有用的内容)。

以下是我尝试过的方法:

  • 在我的批处理脚本末尾添加2>nul没有效果。
  • 在我的批处理脚本末尾添加1>nul会抑制两个错误,这不是我想要的。
  • 在我的批处理脚本末尾添加&set errorlevel=0没有效果。
  • 在我的批处理脚本末尾添加exit 0没有效果。
  • 根据this article在我的.csproj文件末尾添加以下内容可以抑制第一个错误,但会使构建不再失败:
<Target
    Name="PostBuildEvent"
    Condition="'$(PostBuildEvent)'!=''"
    DependsOnTargets="$(PostBuildEventDependsOn)">
    <Exec WorkingDirectory="$(OutDir)" Command="$(PostBuildEvent)" IgnoreExitCode="true" />
</Target>

最后一个选项几乎满足我的需求。但是尽管有错误提示,错误列表并没有弹出,构建也没有失败。似乎任何导致初始错误消息不出现的情况都会导致构建不再失败。是这样吗?还是有某种方法可以使构建失败而显示初始错误消息?

我不知道这是否适用于您的情况,但也许您可以像这里所解释的那样重定向错误输出(这是一个问题的第二个答案,但由于您没有提到它,所以我在这里提供)。 - colinD
@colinD 感谢您的建议。不幸的是,这对我没有用,因为那样我就得不到任何错误消息,包括我实际想要的那些。我唯一想要抑制的消息是 VS 输出整个 post-build 脚本的内容并说它以代码 -1 退出的初始消息。(我可以修改我的问题使其更清晰明了。) - inejwstine
哦,好的,其实很清楚了。你是在使用“exec”任务吗? - colinD
@colinD 这是一个后构建事件。不确定是否是同一件事? - inejwstine
我已经编辑了我的问题,以便更加清晰简洁。 - inejwstine
2个回答

5
你可以通过同时使用 execerror 任务来解决此问题。
你需要编辑 .csproj 文件,并在上一步的最后一个 bullet point 后添加这些任务。
此解决方案通过获取您的 exec 任务的 ExitCode 和 Output,然后使用它们触发 error 任务,该任务将停止构建并记录消息来实现。
Exec 任务需要三个参数:
- IgnoreStandardErrorWarningFormat 和 IgnoreExitCode 防止在此步骤中记录错误 - ConsoleToMsBuild 参数是必需的,以获取输出(在 VS 2017 中拼写为 ConsoleToMSBuild)。
因此,任务看起来像这样:
  <Target Name="PostBuild" AfterTargets="PostBuildEvent">
    <Exec Command="$(PostBuildEvent)" IgnoreStandardErrorWarningFormat="true" IgnoreExitCode="true" ConsoleToMsBuild="true">
      <Output TaskParameter="ConsoleOutput" PropertyName="OutputMessage" />
      <Output TaskParameter="ExitCode" PropertyName="ExitCode" />
    </Exec>
    <Error Text="$(OutputMessage)" Condition="$(ExitCode) == 10" />
    <!-- <Error Text="(optional text) : $(OutputMessage)" Condition="$(ExitCode) == 11" />
    <Error Text="(optional text) : $(OutputMessage)" Condition="$(ExitCode) == 12" /> -->
  </Target>

并编辑文件 foobar.bat

echo foobar : error 1: This is a test error.
exit /b 10 <-- /b parameter needed if used in a .bat file

重要部分是 exit,它将设置我们之后想要使用的代码。
您可以拥有多个 Error 任务以进行更多条件记录或仅使用输出。

我会调查一下。谢谢! - inejwstine
哦,对不起,那不太清楚。当您在Visual Studio中添加“Build Events”时,它会在您的.csproj中写入一个“basic”目标,但您无法访问更多参数,因此需要手动编辑它。所以您仍然可以使用VS编写活动,就像您之前一样,然后编辑该文件(如果您更改了“Build Events”,则将在.csproj中看到修改)。 - colinD
此外,您在编辑中添加的“目标”将覆盖事件,您可以将其删除并仅使用初始的“PostBuildEvent”,就像在此答案中一样。 - colinD
一旦我将上述目标添加到我的.csproj中,它就不再显示我之前看到的初始错误消息,但仍然会显示两个错误消息。第一个错误消息说“foobar:error 1:这是一个测试错误。”而第二个错误消息(我想要的那个)与之前相同。 然而,我仍然接受这个答案,因为现在我可以将消息从“$(OutputMessage)”更改为比以前更具描述性/有用的内容。 谢谢! - inejwstine
很奇怪,我只有一个。我用VS2019测试过了,但根据文档,它应该适用于VS2017。你是否加了 IgnoreStandardErrorWarningFormat="true"?否则,我认为你可以通过不遵循错误格式(因此只需输入 echo:this is a test 而不是 error 1:)来摆脱它。 - colinD
显示剩余4条评论

0

关于:在我的批处理脚本末尾添加&set errorlevel=0没有效果。

如果要忽略单个命令的退出代码,请使用||而不是&或&&。例如:

Robocopy || set errorlevel=0

这段代码的意思是只有当RoboCopy退出错误级别为非零时,才将错误级别设置为0。

"&&" 在这个批处理文件中是什么作用?[1]解释了这个问题以及更多内容。

历史注记:单个“&”符号,例如

(prog1 arg1 arg2) & (cmd2 arg1 arg2 arg3)

运行两个命令。在DOS中并不是很有用。在Unix中,它同时运行两个命令(2个进程),等待两者都完成。由于DOS不支持多进程,“&”只是顺序运行的语法糖。

单管道prog1 | prog2 在DOS中也存在同样的限制。在Unix中,当prog1在stdout上写入适量数据后,它就可以被prog2在stdin上使用。

在DOS中,这相当于速记

prog1 > tmpFile
prog2 < tmpFile

在许多情况下,这样做效果不错。在 write1Meg | head (或更多) 的简单情况下, DOS 必须运行到完成,然后 head 才能在读取第一行的 10 行后退出。
& 做什么? Unix 还支持在命令行末尾使用 &,如下所示: prog1 & 这将启动 prog1 并迅速返回控制台。
&& 和 || 只有在您知道 0 的退出代码被视为“true”,而非零退出代码被视为“false”时才有意义。此外,进行短路评估,在检查第一个命令的退出代码后,执行第二个命令。
prog1 && prog2

在prog1退出后,只有当exitcode == 0时,prog2才会运行

prog1 || prog2

当prog1退出时,只有exitcode != 0时,prog2才会运行。


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